像这样使用描述符协议:
import functoolsclass 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] def __get__(self, instance, instancetype): """Implement the descriptor protocol to make decorating instance method possible. """ # Return a partial function with the first argument is the instance # of the class decorated. return functools.partial(self.__call__, instance)编辑:
如何运作?
在装饰器中使用描述符协议将使我们能够以正确的实例作为自身来访问装饰的方法,也许一些代码可以提供更好的帮助:
现在,当我们要做的时候:
class Session(p.Session): ... @cacher def get_something(self): print "get_something called with self = %s "% self return self.pl.get_something()
相当于:
class Session(p.Session): ... def get_something(self): print "get_something called with self = %s "% self return self.pl.get_something() get_something = cacher(get_something)
因此,现在get_something是cacher的实例。因此,当我们调用方法get_something时,它将被转换为此(由于描述符协议):
session = Session()session.get_something # <==> session.get_something.__get__(get_something, session, <type ..>)# N.B: get_something is an instance of cacher class.
并且因为:
session.get_something.__get__(get_something, session, <type ..>)# returnget_something.__call__(session, ...) # the partial function.
所以
session.get_something(*args)# <==>get_something.__call__(session, *args)
希望这会解释它是如何工作的:)



