I'm new to Python decorators (wow, great feature!), And itβs not easy for me to get the following to work, because the self argument takes the form of confusion.
#this is the decorator class cacher(object): def __init__(self, f): self.f = f self.cache = {} def __call__(self, *args): fname = self.f.__name__ if (fname not in self.cache): self.cache[fname] = self.f(self,*args) else: print "using cache" return self.cache[fname] class Session(p.Session): def __init__(self, user, passw): self.pl = p.Session(user, passw) @cacher def get_something(self): print "get_something called with self = %s "% self return self.pl.get_something() s = Session(u,p) s.get_something()
When I run this, I get:
get_something called with self = <__main__.cacher object at 0x020870F0> Traceback: ... AttributeError: 'cacher' object has no attribute 'pl'
for the line where I am self.cache[fname] = self.f(self,*args)
Problem . Obviously, the problem is that self is a cacher object instead of a session instance that does not really have the pl attribute. However, I cannot find how to solve this.
The solutions that I examined but cannot use - I thought that the decorator class would return a function instead of a value (as in section 2.1 of this article ), so that self is evaluated in the correct context, but this is not possible, since my decorator is implemented as a class and uses the built-in __call__ . Then I decided not to use the class for my decorator, so I do not need the __call__ method, but I can not do this because I need to maintain state between calls to the decorator (i.e., to track what is in self.cache ) .
Question So, besides using the global cache dictionary variable (which I have not tried, but I guess it will work), is there any other way to make this decorator work?
Edit: this SO question is similar to Decorating python class methods, how do I pass an instance to a decorator?
python decorator python-decorators
Rabarberski Mar 29 '11 at 8:45 2011-03-29 08:45
source share