Second Chapter : De Mystifying Decorators in Python

we have a class that does a lot of very important stuff and we want to time everything it does. Then we should use something like a time_this decorator on every method inside the class:

That would work just fine. But it’s quite a few extra lines of code within the class. And what if we write some more class methods and forget to decorate one of them? What if we decide we dont want to time the class any more? There is definitely space for human error here. It would be much nicer to write it like this:

As you know by now, that code is equivalent to:

So how would time_all_class_methods work?
Firstly, we know it needs to take in a class as an argument, and return a class. We also know that the functions of the returned class should look the same as the functions of the original ImportantStuff class. That is, we still want to be able to do our important stuff, we just want to time it as well. And here is how we will do it:

In the code above

x = self.oInstance.__getattribute__(s)

This needs an explanation on __getattribute__ why we are doing this ?

__getattribute__

If we have __getattribute__ method in our 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.

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]