I think I need to make things a little bit clearer with the code shown in previous post...
The Decoration
Decorating a function enables you to call other code before the original function is called, or you can completely change the functions code. As I've red somewhere it is best equated to preprocessor macros or template libraries in C++.
In my previous post, I've decorated my class methods by adding
By decorating my functions with a class (you can decorate them with functions too), I'm practically turning them in to classes. So instead of being a method of a class, they become a class belonging to another class.
The key to decorate a Class method in a way to be able to reach the instance object is to store the instance object in the
The order of execution of the CachedMethod classes methods are like that: when you import your module the functions are decorated, and the
The
You can change the settings of the arguments of
CachedMethod Explained
Here are the brief explanation of what is going on in the methods of CachedMethod class.
Thats all... Hope it helps you to understand what is going on. And if not, there are some nice tutorials here and here is a nice function decorator library in Python.org
The Decoration
Decorating a function enables you to call other code before the original function is called, or you can completely change the functions code. As I've red somewhere it is best equated to preprocessor macros or template libraries in C++.
In my previous post, I've decorated my class methods by adding
@CachedMethod
at the definition of the class method. This is one of the two ways of defining decorators. When I do that the Python interpreter decorates the unbound function, which means, it is decorated whenever I've imported the module not when I've created the instance object. This leads us to a little but important difference that can easily be neglected, so be careful to not to miss what you intended to do. I mean, when I've first written the CachedMethod class, it was caching the data in the Class not in the instance object. So every instance of that class was trying to use the same cached data, which in my situation was a wrong behaviour, though it is may desirable in some other cases...By decorating my functions with a class (you can decorate them with functions too), I'm practically turning them in to classes. So instead of being a method of a class, they become a class belonging to another class.
The key to decorate a Class method in a way to be able to reach the instance object is to store the instance object in the
__get__
method of the decorator and then use it in the __call__
method.The order of execution of the CachedMethod classes methods are like that: when you import your module the functions are decorated, and the
__init__
of the CachedMethod runs for all of the class methods you have decorated. Then when you create your object nothing happens, but when you call a decorated method, first the __get__
method runs, than the __call__
method. It is a good practice to add print()
commands to the decorators method to understand what is going on.The
__get__
method has 3 arguments self, instance and class. Self, as regular, is the CachedMethod instance, instance is the instance of which the decorated function belongs to, and the class is the super that the instance is derived from.You can change the settings of the arguments of
__call__
method, but I think the best settings
is a couple of *args
, **keys
together ( def __call__(self, *args, **keys)
) . So you can get any type of arguments setup passed to your original function and use them in your decorator. Other than this setup you can use the same argument count and order in your original function, but I don't recommend that, because you are restricted to decorate only the methods that has the same types of arguments.CachedMethod Explained
Here are the brief explanation of what is going on in the methods of CachedMethod class.
__init__
: I store unbound method and the name of the unbound method in class variables, to let my self to call the original function later on.__get__
: as far as I know, this is the only place that I can get the instance object. I store the instance object in self._obj
and check if it already has its attributes set up. If not I create the attributes by using setattr
commands__call__
: I've all the data I need to have, so I do the caching by calling the original function if the self._data
is empty or the time delta is bigger than the self._maxTimeDelta
, otherwise I return the cached data. To get the data from the instance appropriately I use getattr
, and I evaluate the attribute name on the fly by using self._name + '_data'
for example.Thats all... Hope it helps you to understand what is going on. And if not, there are some nice tutorials here and here is a nice function decorator library in Python.org
Comments