__getattr__ vs. __getattribute__ — What’s the Difference?

Rate this post

As a programmer, you generally appreciate more control of your data and more control on the behavior of my program itself. It is in this moment when Python comes in our help with all its power letting us get right into the flow of our programming, avoiding us to lose something like define an attribute or get unexpected visitors inside our data.

As Python has constructors and destructors for the classes, so you can define tasks on the creation or destruction of the class, Python can intercept the calling of an specific attribute or even the calling of a not defined one.

__getattr__

What if you don’t define an attribute? Let’s see:

class Running:
    def __init__(self, start, finish):
        self.start=start
        self.finish=finish


obj1 = Running(1, 10)

print(obj1.start)
# 1

print(obj1.finish)
# 10

print(obj1.anewone)
# --> AttributeError: 'Running' object has no attribute 'anewone'

In this example we have defined two attributes for the class Running, start and finish during the construction of the class, then after instantiate the class in obj1 we try to print the contents of start, finish and a new attribute not defined call anewone, raising an Attribute Error exception that exits our program. Bang!

To prevent that previous issue you must call our dearest __getattr__ it will intercept the request over that unknown attribute and will do something about it.

class Running:
    def __init__(self, start, finish):
        self.start=start
        self.finish=finish


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


obj1 = Running(1, 10)

print(obj1.start)
# 1

print(obj1.finish)
# 10

print(obj1.anewone)
# 0

What did happen here?

All seems to be the same, but wait, the __getattr__ keyword is doing something there, assigning zero to the unknown attribute and returning it to show without raising any exception. Cool ah?

What else can I do with attributes?

Well, what if we want to prevent someone from accessing our attributes that starts with a specific substring? That one is hard ah? We would need to run through every attribute defined looking for the forbidden substring and then raise some kind of exception to warn about that protected name of the attribute. How can we do that?

Oh, don´t tell me, another dundee boy.

Yes! __getattribute__

__getattribute__

 If you have __getattribute__ method in your class, Python invokes this method for every attribute regardless whether it exists or not.

Let´s see:

class Running:
    def __init__(self, start, finish):
        self.start=start
        self.finish=finish


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



obj1 = Running(1, 10)

print(obj1.start)
# 1

print(obj1.finish)
# 10

print(obj1.anewone)
# ... AttributeError

Now you can see how the if condition looks for the substring “ane” at the beginning of every attribute’s name and raise an exception AttributeError when it gets the condition. Easy Peasy.

What if we use the two keywords in the same Class?

Nooo, its the end of world!

Just joking. That is a good question because if the both dundee friends are in the class, __getattribute__ run first (remember it looks into every attribute) and if __getattribute__ need to raise an AttributeError exception, nothing happens and __getattr__ takes the control and do it job. Take care.

Hope you have take some new insights about these dundee boys __getattr__ and __getattribute__ they looks like being the same but they are very different between them.