This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author rhettinger
Recipients docs@python, jdemeyer, jdufresne, rhettinger
Date 2019-08-29.04:51:58
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1567054318.94.0.727992928146.issue36743@roundup.psfhosted.org>
In-reply-to
Content
Collecting various factlets on this topic

PEP 252 gives the specification for the descriptor protocol: "__get__(): a function callable with one or two arguments that retrieves the attribute value from an object."

function_get, property_get, classmethod_get, and staticmethod_get all support calls with one or two arguments:

    >>> a = A()
    >>> class A:
            def m(self):
                return 42
            @property
            def p(self):
                return 43
            @classmethod
            def c(cls):
                return 44
            @staticmethod
            def s():
                return 45
            
    >>> a = A()
    >>> vars(A)['m'].__get__(a)()
    42
    >>> vars(A)['m'].__get__(a, A)()
    42
    >>> vars(A)['p'].__get__(a)
    43
    >>> vars(A)['p'].__get__(a, A)
    43
    >>> vars(A)['c'].__get__(a)()
    44
    >>> vars(A)['c'].__get__(a, A)()
    44
    >>> vars(A)['s'].__get__(a)()
    45
    >>> vars(A)['s'].__get__(a, A)()
    45

Python functions that comply with the specification should also do the same (as taught by the descriptor HOWTO).  That said, I have found multiple Python functions that aren't providing the None default.  I will fix those as I find them.

type.__getattribute__, object.__getattribute__ and super.__getattribute__ always call __get__ with both attributes specified:

    >>> class D:
            def __get__(*args):
                print(args)

    >>> class C:
            d = D()

    >>> class S(C):
            def f(self):
                return super().d
        
    >>> C.d
    (<__main__.D object at 0x104d967f0>, None, <class '__main__.C'>)
    >>> C().d
    (<__main__.D object at 0x104d967f0>, <__main__.C object at 0x104df77c0>, <class '__main__.C'>)
    >>> S().f()
    (<__main__.D object at 0x104d967f0>, <__main__.S object at 0x104df7580>, <class '__main__.S'>
History
Date User Action Args
2019-08-29 04:51:58rhettingersetrecipients: + rhettinger, docs@python, jdemeyer, jdufresne
2019-08-29 04:51:58rhettingersetmessageid: <1567054318.94.0.727992928146.issue36743@roundup.psfhosted.org>
2019-08-29 04:51:58rhettingerlinkissue36743 messages
2019-08-29 04:51:58rhettingercreate