reference:
https://docs.python.org/3/howto/descriptor.html
http://www.cs.utexas.edu/~cannata/cs345/Class%20Notes/15%20python_attributes_and_methods.pdf
python attribute search summary:
1. retrieve attribute from an object objectname.attrname
1. if attrname is python built-in attribute, just return it.
2. search objectname.__class__.__dict__ for attrname, return if it is a data descriptor. recursively search all bases of objectname.__class__
3. search objectname.__dict__ for attrname, return if found. if objectname is a class, search its bases, if a descriptor exists in it or its bases, return the descriptor result.
4. search objectname.__base__.__dict__ for attrname
if it is non-data descriptor --> return
if it is not a descriptor --> return
search its bases
- set attribute from an object
objectname.attrname = something
1. check objectname.__class__.__dict__ for attrname, if it exists and is a data-descriptor, use that descriptor. search all bases of objectname.__class__
2. insert something into objectname.__dict__ for key attrname
for attribute retrieve, __dict__ has higher priority than non-data descriptor.
for attribute set, __dict__ has lower priority than data descriptor.
two types of descriptor:
data descriptor
non-data descriptor