【发布时间】:2011-07-25 02:33:03
【问题描述】:
我是 Python 装饰器的新手(哇,很棒的功能!),但由于 self 参数有点混淆,我无法让以下内容正常工作。
#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()
当我运行它时,我得到:
get_something called with self = <__main__.cacher object at 0x020870F0>
Traceback:
...
AttributeError: 'cacher' object has no attribute 'pl'
对于我做self.cache[fname] = self.f(self,*args)的那一行
问题 - 显然,问题在于self 是缓存对象而不是Session 实例,它确实没有pl 属性。但是我找不到如何解决这个问题。
我考虑过但不能使用的解决方案 - 我想让装饰器类返回一个函数而不是一个值(就像在这个 article 的第 2.1 节中一样),以便 @ 987654329@ 在正确的上下文中进行评估,但这是不可能的,因为我的装饰器是作为一个类实现的并且使用内置的 __call__ 方法。然后我想不为我的装饰器使用一个类,这样我就不需要 __call__ 方法,但我不能这样做,因为我需要在装饰器调用之间保持状态(即用于跟踪self.cache 属性中的内容)。
问题 - 那么,除了使用全局 cache 字典变量(我没有尝试过,但假设会起作用)之外,还有其他方法可以使这个装饰器工作吗?
编辑:这个 SO 问题似乎很相似 Decorating python class methods, how do I pass the instance to the decorator?
【问题讨论】:
-
您知道这样
Session的所有实例都将共享同一个缓存吗? -
是的,我还没有完成代码,但我大致想到了在某个地方提供一个额外的会话参数来保持单独的缓存。