[issue36743] Docs: Descript __get__ signature defined differently across the docs

New submission from Jon Dufresne <jon.dufresne@gmail.com>: Here: https://docs.python.org/3/reference/datamodel.html#object.__get__ The __get__ signature is defined as: object.__get__(self, instance, owner) But here: https://docs.python.org/3/howto/descriptor.html#descriptor-protocol It is defined as: descr.__get__(self, obj, type=None) It is not clear to me as a reader if all descriptors should have the owner/type argument default to None or if it should be required. If it should default to None, I think all doc examples should follow this expectation to make it clear to someone implementing a descriptor for the first time. As best I can tell, the owner/type is always passed. So perhaps the =None shouldn't be there. Grepping the CPython code, I see lots of definitions for both required and optional, adding more confusion for me. If there is a definitive answer, I'm happy to follow through by updating the docs. ---------- assignee: docs@python components: Documentation messages: 341004 nosy: docs@python, jdufresne priority: normal severity: normal status: open title: Docs: Descript __get__ signature defined differently across the docs versions: Python 2.7, Python 3.5, Python 3.6, Python 3.7, Python 3.8, Python 3.9 _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue36743> _______________________________________

Change by Karthikeyan Singaravelan <tir.karthi@gmail.com>: ---------- nosy: +rhettinger _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue36743> _______________________________________

Raymond Hettinger <raymond.hettinger@gmail.com> added the comment: Perhaps the datamodel docs can be clarified to note that callers are allowed to omit the third argument (which usually only makes sense when the second argument is not None). FWIW, section 3.3.2.3 already has an example of a direct call to a __get__ descriptor with only the *obj* argument. ---------- assignee: docs@python -> rhettinger versions: -Python 2.7, Python 3.5, Python 3.6, Python 3.9 _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue36743> _______________________________________

Change by Raymond Hettinger <raymond.hettinger@gmail.com>: ---------- keywords: +patch pull_requests: +12915 stage: -> patch review _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue36743> _______________________________________

Jeroen Demeyer <J.Demeyer@UGent.be> added the comment: Personally, I have always found "instance" and "owner" very confusing names for these arguments. If you want to change the documentation, I would recommend changing those names too. Better names would be "obj" and "cls" or something like that. ---------- nosy: +jdemeyer _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue36743> _______________________________________

Jeroen Demeyer <J.Demeyer@UGent.be> added the comment:
Perhaps the datamodel docs can be clarified to note that callers are allowed to omit the third argument
That's not true in general, only when __get__ is a slot wrapper (i.e. for classes implemented in C). When __get__ is a Python function, nothing special is done, it's just a Python function. ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue36743> _______________________________________

Raymond Hettinger <raymond.hettinger@gmail.com> added the comment: 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'> ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue36743> _______________________________________

Raymond Hettinger <raymond.hettinger@gmail.com> added the comment: New changeset 0dac68f1e593c11612ed54af9edb865d398f3b05 by Raymond Hettinger in branch 'master': bpo-36743: __get__ is sometimes called without the owner argument (#12992) https://github.com/python/cpython/commit/0dac68f1e593c11612ed54af9edb865d398... ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue36743> _______________________________________

Change by miss-islington <mariatta.wijaya+miss-islington@gmail.com>: ---------- pull_requests: +15265 pull_request: https://github.com/python/cpython/pull/15589 _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue36743> _______________________________________

Change by Raymond Hettinger <raymond.hettinger@gmail.com>: ---------- resolution: -> fixed stage: patch review -> resolved status: open -> closed _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue36743> _______________________________________

Raymond Hettinger <raymond.hettinger@gmail.com> added the comment: New changeset c71ae1a45bd6e6d0f5aebc470b35f5a7dc0d8078 by Raymond Hettinger (Miss Islington (bot)) in branch '3.8': bpo-36743: __get__ is sometimes called without the owner argument (GH-12992) (GH-15589) https://github.com/python/cpython/commit/c71ae1a45bd6e6d0f5aebc470b35f5a7dc0... ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue36743> _______________________________________
participants (5)
-
Jeroen Demeyer
-
Jon Dufresne
-
Karthikeyan Singaravelan
-
miss-islington
-
Raymond Hettinger