.. include:: global.rst ============================================= 11: Custom Attribute Access ============================================= Summary ============ - The descriptor object can customize to any attribute via the __get__, __set__ and __delete__ functions which are automatically called on attribute access or deletion - If a descriptor defines __get__ and __set__ then it is a data descriptor - If only __get__ is defined it is a non-data descriptor - Data descriptors cannot be overridden by a definition in the instance, whereas non-data descriptors can be - __getattribute__ is called for every attribute access and if you override it then you override every attribute access - If __getattribute__ fails to find an attribute then it automatically calls __getattr__, if it is defined - __setattr__ is called every time you attempt an assignment to an attribute - You can use __getattr__ to implement default attributes and methods - You can use del or delattr to delete an attribute, but in either case __delattr__ is called, if it is defined - The __dir__ magic method can be used to define a custom dir command - Slots are just a more efficient way of implementing attributes using a descriptor - Another way of accessing attributes is via the index or key operator, [] - This is customized using __getitem__ and __setitem__ - There are also a range of addirtional magic methods that can make attribute access look more like a collection Program ============ .. literalinclude:: programs/chapterEleven.py :language: python Program Output ================= .. code-block:: console [__setattr__] Setting slot_attr = I am in slots --- DATA DESCRIPTOR --- [__setattr__] Setting data = 10 [DataDescriptor __set__] Setting data = 10 [__getattribute__] Accessing: __dict__ [__getattribute__] Accessing: data [DataDescriptor __get__] Getting data [__getattribute__] Accessing: __dict__ 10 [__delattr__] Deleting data [DataDescriptor __delete__] Deleting data [__getattribute__] Accessing: __dict__ --- NON-DATA DESCRIPTOR --- [__getattribute__] Accessing: non_data [NonDataDescriptor __get__] Accessed default [__setattr__] Setting non_data = override [__getattribute__] Accessing: non_data override --- __getattr__ FALLBACK --- [__getattribute__] Accessing: missing_attr [__getattribute__] Accessing: __getattr__ [__getattr__] missing_attr not found, returning default default_missing_attr --- __setattr__ --- [__setattr__] Setting new_attr = 42 --- __delattr__ --- [__delattr__] Deleting new_attr --- __dir__ --- ['custom_attr1', 'custom_attr2', 'data', 'non_data'] --- __slots__ --- [__getattribute__] Accessing: slot_attr I am in slots --- COLLECTION ACCESS --- [__setitem__] Setting key: key = value [__getattribute__] Accessing: __dict__ [__getitem__] Getting key: key [__getattribute__] Accessing: __dict__ valuec