[Tutor] @property for old style classes vs new style classes

eryk sun eryksun at gmail.com
Fri Sep 16 02:31:35 EDT 2016


On Thu, Sep 15, 2016 at 9:48 PM, monikajg at netzero.net
<monikajg at netzero.net> wrote:
> But why var is in class __dict__?
> Does @property make it a class attribute?

An instance of `property` is a data descriptor, i.e. it implements the
__get__, __set__, and __delete__ methods of the descriptor protocol. A
non-data descriptor only implements __get__. Descriptors are
fundamental to the way attribute lookup works in Python. See the
descriptor howto guide:

https://docs.python.org/3/howto/descriptor.html

The above document paints a picture of attribute access that's not
really accurate at times. Also, the example code that attempts to
demonstrate type.__getattribute__ in terms of object.__getattribute__
is wrong. (It fails to search the __mro__ of the class, only the
metaclass. Also, what it's trying to do is fundamentally impossible.
You can't know whether object.__getattribute___ already evaluated a
descriptor that it found in the metaclass.)

Here's an overview of how object.__getattribute__ works:

    * If a data descriptor is found in the class, call its __get__
      method, passing it the instance and the class, and return the
      result.
    * Else if the instance has a dict and the name is found in it,
      return the value from the instance dict.
    * Else if a non-data descriptor is found in the class, call its
      __get__ method, passing it the instance and the class, and
      return the result.
    * Else if a non-descriptor is found in the class, return it.
    * Else raise AttributeError.

A class lookup searches the dicts of each class in the __mro__,
stopping on the first hit. Also, a type can define a __getattr__
fallback method, in which case the AttributeError raised by
__getattribute__ is ignored.

For type.__getattribute__, the class object in this case is handled as
an instance of the metaclass. The main difference compared to
object.__getattribute__ is in the second step, since the instance in
this case is a class. Instead of searching just the class dict, it
searches the dicts of each class in the __mro__. Also, if it finds a
descriptor in the class __mro__, it calls its __get__ method, passing
None for the instance.


More information about the Tutor mailing list