python – Difference between __getattr__ vs __getattribute__

The Question :

448 people think this question is useful

I am trying to understand when to use __getattr__ or __getattribute__. The documentation mentions __getattribute__ applies to new-style classes. What are new-style classes?

The Question Comments :

The Answer 1

527 people think this answer is useful

A key difference between __getattr__ and __getattribute__ is that __getattr__ is only invoked if the attribute wasn’t found the usual ways. It’s good for implementing a fallback for missing attributes, and is probably the one of two you want.

__getattribute__ is invoked before looking at the actual attributes on the object, and so can be tricky to implement correctly. You can end up in infinite recursions very easily.

New-style classes derive from object, old-style classes are those in Python 2.x with no explicit base class. But the distinction between old-style and new-style classes is not the important one when choosing between __getattr__ and __getattribute__.

You almost certainly want __getattr__.

The Answer 2

157 people think this answer is useful

Lets see some simple examples of both __getattr__ and __getattribute__ magic methods.

__getattr__

Python will call __getattr__ method whenever you request an attribute that hasn’t already been defined. In the following example my class Count has no __getattr__ method. Now in main when I try to access both obj1.mymin and obj1.mymax attributes everything works fine. But when I try to access obj1.mycurrent attribute — Python gives me AttributeError: 'Count' object has no attribute 'mycurrent'

class Count():
    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.mycurrent)  --> AttributeError: 'Count' object has no attribute 'mycurrent'

Now my class Count has __getattr__ method. Now when I try to access obj1.mycurrent attribute — python returns me whatever I have implemented in my __getattr__ method. In my example whenever I try to call an attribute which doesn’t exist, python creates that attribute and set it to integer value 0.

class Count:
    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax    

    def __getattr__(self, item):
        self.__dict__[item]=0
        return 0

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.mycurrent1)

__getattribute__

Now lets see the __getattribute__ method. If you have __getattribute__ method in your class, python invokes this method for every attribute regardless whether it exists or not. So why we need __getattribute__ method? One good reason is that you can prevent access to attributes and make them more secure as shown in the following example.

Whenever someone try to access my attributes that starts with substring ‘cur’ python raises AttributeError exception. Otherwise it returns that attribute.

class Count:

    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax
        self.current=None

    def __getattribute__(self, item):
        if item.startswith('cur'):
            raise AttributeError
        return object.__getattribute__(self,item) 
        # or you can use ---return super().__getattribute__(item)

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.current)

Important: In order to avoid infinite recursion in __getattribute__ method, its implementation should always call the base class method with the same name to access any attributes it needs. For example: object.__getattribute__(self, name) or super().__getattribute__(item) and not self.__dict__[item]

IMPORTANT

If your class contain both getattr and getattribute magic methods then __getattribute__ is called first. But if __getattribute__ raises AttributeError exception then the exception will be ignored and __getattr__ method will be invoked. See the following example:

class Count(object):

    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax
        self.current=None

    def __getattr__(self, item):
            self.__dict__[item]=0
            return 0

    def __getattribute__(self, item):
        if item.startswith('cur'):
            raise AttributeError
        return object.__getattribute__(self,item)
        # or you can use ---return super().__getattribute__(item)
        # note this class subclass object

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.current)

The Answer 3

16 people think this answer is useful

This is just an example based on Ned Batchelder’s explanation.

__getattr__ example:

class Foo(object):
    def __getattr__(self, attr):
        print "looking up", attr
        value = 42
        self.__dict__[attr] = value
        return value

f = Foo()
print f.x 
#output >>> looking up x 42

f.x = 3
print f.x 
#output >>> 3

print ('__getattr__ sets a default value if undefeined OR __getattr__ to define how to handle attributes that are not found')

And if same example is used with __getattribute__ You would get >>> RuntimeError: maximum recursion depth exceeded while calling a Python object

The Answer 4

14 people think this answer is useful

New-style classes inherit from object, or from another new style class:

class SomeObject(object):
    pass

class SubObject(SomeObject):
    pass

Old-style classes don’t:

class SomeObject:
    pass

This only applies to Python 2 – in Python 3 all the above will create new-style classes.

See 9. Classes (Python tutorial), NewClassVsClassicClass and What is the difference between old style and new style classes in Python? for details.

The Answer 5

6 people think this answer is useful

New-style classes are ones that subclass “object” (directly or indirectly). They have a __new__ class method in addition to __init__ and have somewhat more rational low-level behavior.

Usually, you’ll want to override __getattr__ (if you’re overriding either), otherwise you’ll have a hard time supporting “self.foo” syntax within your methods.

Extra info: http://www.devx.com/opensource/Article/31482/0/page/4

The Answer 6

2 people think this answer is useful

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.

The Answer 7

2 people think this answer is useful
  • 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.

The Answer 8

0 people think this answer is useful

I find that no one mentions this difference:

__getattribute__ has a default implementation, but __getattr__ does not.

class A:
    pass
a = A()
a.__getattr__ # error
a.__getattribute__ # return a method-wrapper

This has a clear meaning: since __getattribute__ has a default implementation, while __getattr__ not, clearly python encourages users to implement __getattr__.

Add a Comment