On 5/30/21, Ethan Furman <et...@stoneleaf.us> wrote: > > > Properties are a special kind of attribute. Basically, when Python > encounters the following code: > > > > spam = SomeObject() > > print(spam.eggs) > > > > it looks up eggs in spam, and then examines eggs to see if it has a > __get__, __set__, or __delete__ > > method — if it does, it's a property.
The above is not quite right. Having a __get__ method is not sufficient. In the quoted example, the `eggs` attribute of the SomeObject type has to be a data descriptor type, which means it defines a __set__ and/or __delete__ method. A computed attribute that's implemented by a data descriptor type cannot be overridden by an instance attribute of the same name. In contrast, a non-data descriptor type only defines a __get__ method (e.g. the `function` type is a non-data descriptor). A computed attribute that's implemented by a non-data descriptor type will be overridden by an instance attribute of the same name. The two common data descriptor types are `property` and `member_descriptor` (from __slots__), but creating custom data descriptor types is easy to implement. See "customizing attribute access" in the data model documentation, and in particular "implementing descriptors" and "invoking descriptors": https://docs.python.org/3/reference/datamodel.html#customizing-attribute-access -- https://mail.python.org/mailman/listinfo/python-list