Difference between __getattr__ vs __getattribute__

前端 未结 8 1056
甜味超标
甜味超标 2020-11-22 12:54

I am trying to understand when to use __getattr__ or __getattribute__. The documentation mentions __getattribute__ applies to new-sty

相关标签:
8条回答
  • 2020-11-22 13:17
    • getattribute: Is used to retrieve an attribute from an instance. It captures every attempt to access an instance attribute by using dot notation or getattr() built-in function.
    • getattr: Is executed as the last resource when attribute is not found in an object. You can choose to return a default value or to raise AttributeError.

    Going back to the __getattribute__ function; if the default implementation was not overridden; the following checks are done when executing the method:

    • Check if there is a descriptor with the same name (attribute name) defined in any class in the MRO chain (method object resolution)
    • Then looks into the instance’s namespace
    • Then looks into the class namespace
    • Then into each base’s namespace and so on.
    • Finally, if not found, the default implementation calls the fallback getattr() method of the instance and it raises an AttributeError exception as default implementation.

    This is the actual implementation of the object.__getattribute__ method:

    .. c:function:: PyObject* PyObject_GenericGetAttr(PyObject *o, PyObject *name) Generic attribute getter function that is meant to be put into a type object's tp_getattro slot. It looks for a descriptor in the dictionary of classes in the object's MRO as well as an attribute in the object's :attr:~object.dict (if present). As outlined in :ref:descriptors, data descriptors take preference over instance attributes, while non-data descriptors don't. Otherwise, an :exc:AttributeError is raised.

    0 讨论(0)
  • 2020-11-22 13:20

    In reading through Beazley & Jones PCB, I have stumbled on an explicit and practical use-case for __getattr__ that helps answer the "when" part of the OP's question. From the book:

    "The __getattr__() method is kind of like a catch-all for attribute lookup. It's a method that gets called if code tries to access an attribute that doesn't exist." We know this from the above answers, but in PCB recipe 8.15, this functionality is used to implement the delegation design pattern. If Object A has an attribute Object B that implements many methods that Object A wants to delegate to, rather than redefining all of Object B's methods in Object A just to call Object B's methods, define a __getattr__() method as follows:

    def __getattr__(self, name):
        return getattr(self._b, name)
    

    where _b is the name of Object A's attribute that is an Object B. When a method defined on Object B is called on Object A, the __getattr__ method will be invoked at the end of the lookup chain. This would make code cleaner as well, since you do not have a list of methods defined just for delegating to another object.

    0 讨论(0)
提交回复
热议问题