Search code examples
pythonpython-descriptors

Why is __get__() specified to have an optional third argument?


The Descriptor HowTo Guide (Descriptor protocol) specifies that __get__() must be callable with 2 and 3 arguments:

descr.__get__(self, obj, type=None) -> value

Why has it been defined like this? AFAIK CPython will always call this method with 3 arguments, so that None default argument is never used.

I have seen Why do people default owner parameter to None in __get__?, but that asks a different question, i.e. why people write their descriptors with that signature, not why the signature has been defined to be like this, and none of the current answers go into why it has been specified like this.


Solution

  • I've personally never written a descriptor with a None default - and I had not notcied to this day it was specified as optional.

    However, the text in the data model contains what I think you want as an answer:

    PEP 252 specifies that __get__() is callable with one or two arguments. Python’s own built-in descriptors support this specification; however, it is likely that some third-party tools have descriptors that require both arguments. Python’s own __getattribute__() implementation always passes in both arguments whether they are required or not.

    So, although PEP 252 specifies the 3rd argument as optional, the language itself will always fill in both instance and owner parameters, and few people care, when writing descriptors, for an eventual possible manually written call to __get__ which might ommit the owner. And, on the other hand, people who specify the default None to owner will do so because the docs, as you've noted, say that it should be optional.