Difference between __getattr__ and __getattribute__
Asked Answered
M

8

586

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

Molliemollify answered 19/7, 2010 at 2:11 Comment(2)
possible duplicate of Understanding the difference between __getattr__ and __getattribute__Canny
@Trilarion yet that question mentions an answer from here...Katusha
Q
680

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__.

Quantic answered 19/7, 2010 at 2:22 Comment(7)
Can I implement both of them in the same class? If I can, what is it for implementing the both?Cassandra
@Alcott: you can implement them both, but I'm not sure why you would. __getattribute__ will be called for every access, and __getattr__ will be called for the times that __getattribute__ raised an AttributeError. Why not just keep it all in one?Quantic
@NedBatchelder, if you want to (conditionally) override calls to existing methods, you would want to use __getattribute__.Joann
"In order to avoid infinite recursion in this 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)."Mcduffie
@kmonsoor. That's a good reason to implement both. objec.__getattribute__ invokes myclass.__getattr__ under the right circumstances.Baleen
Just a note: to access a variable within __getattribute__ without invoking infinite recursion, super().__getattribute__(item) must be calledStodge
I have this worry, is there any disadvantage to directly using super().__getattribute__(item), because more resources online suggestion object.__getattribute__(item) (even the Python official documentation used the base class object attribute access directly ). I would think that it makes more sense to use super since this attribute customization might be implemented by a parent class and using super simply skips their accessLati
L
244

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 sets 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 do 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)
Lancewood answered 5/8, 2016 at 11:37 Comment(2)
I am not sure what exactly would be use case for overriding __getattribute__ but surely this isn't. Because per your example, all you are doing in __getattribute__ is raising AttributeError exception if the attribute isn't there in __dict__ of the object; but you don't really need this because this is default implementation of __getattribute__ and infact __getattr__ is exactly what you need as a fallback mechanism.Lloyd
@Lloyd current is defined on instances of Count (see __init__), so simply raising AttributeError if the attribute isn't there isn't quite what's happening - it defers to __getattr__ for all names starting 'cur', including current, but also curious, curly ...Invariable
S
21

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

Stride answered 16/9, 2013 at 6:11 Comment(5)
Actually, this is terrible. Real-world __getattr__() implementations only accept a finite set of valid attribute names by raising AttributeError for invalid attribute names, thereby avoiding subtle and difficult-to-debug issues. This example unconditionally accepts all attribute names as valid – a bizarre (and frankly error-prone) misuse of __getattr__(). If you want "total control" over attribute creation as in this example, you want __getattribute__() instead.Diagnostician
@CecilCurry: All the issues that you linked to involve implicitly returning None rather than a value, which this answer doesn't do. What's wrong with accepting all attribute names? It's the same as a defaultdict.Lefthanded
The problem is that __getattr__ will be called before superclass lookup. This is OK for a direct subclass of object, since the only methods you really care about there are magic methods that ignore the instance anyway, but for any more complex inheritance structure, you completely remove the ability to inherit anything from the parent.Baleen
@Simon K Bhatta4ya, your last print statement is a comment. Right? It's a long line and tedious to read (One has to scroll a lot in the right side). What about putting the line after the code section? Or if you want to put it in the code section, I think it would be better to break it into two different lines.Petulant
Note that in f.x = 3, __getattr__() is not called, but __setattr__() is. In this case, since it's not implemented, the default version is inherited from object.Manvil
L
16

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.

Lemmie answered 19/7, 2010 at 2:18 Comment(1)
What does this have to do with the question? LolEveevection
H
7

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

Heyerdahl answered 19/7, 2010 at 2:18 Comment(0)
A
6
  • 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.

Agitato answered 21/6, 2020 at 8:28 Comment(0)
P
6

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__.

Photomicroscope answered 13/8, 2020 at 18:14 Comment(2)
Does python2 does not have default getattribute ?Mcintyre
New style classes (which is the default in Python3) behave the same in both Python versions in this regard. (Python2 old style classes do not have a default __getattribute__.)Repertory
C
5

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.

Colb answered 13/4, 2020 at 13:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.