是否有一种简洁的方法让装饰器仅在实例化类的实例时调用类的实例方法?
class C:
def instance_method(self):
print('Method called')
def decorator(f):
print('Locals in decorator %s ' % locals())
def wrap(f):
print('Locals in wrapper %s' % locals())
self.instance_method()
return f
return wrap
@decorator
def function(self):
pass
c = C()
c.function()
我知道这不起作用,因为 self
在调用 decorator
时未定义(因为它没有作为实例方法调用,因为没有可用的引用类)。然后我想出了这个解决方案:
class C:
def instance_method(self):
print('Method called')
def decorator():
print('Locals in decorator %s ' % locals())
def wrap(f):
def wrapped_f(*args):
print('Locals in wrapper %s' % locals())
args[0].instance_method()
return f
return wrapped_f
return wrap
@decorator()
def function(self):
pass
c = C()
c.function()
这利用了这样一个事实,即我知道任何实例方法的第一个参数都是 self
。这个包装器定义方式的问题是每次执行函数时都会调用实例方法,这是我不希望的。然后我想出了以下有效的轻微修改:
class C:
def instance_method(self):
print('Method called')
def decorator(called=[]):
print('Locals in decorator %s ' % locals())
def wrap(f):
def wrapped_f(*args):
print('Locals in wrapper %s' % locals())
if f.__name__ not in called:
called.append(f.__name__)
args[0].instance_method()
return f
return wrapped_f
return wrap
@decorator()
def function(self):
pass
c = C()
c.function()
c.function()
现在该函数只被调用一次,但我不喜欢每次调用该函数时都必须进行此检查的事实。我猜没有办法解决它,但如果有人有任何建议,我很想听听他们的意见!谢谢:)
最佳答案
我想出了一个可能的替代解决方案。我喜欢它,因为在定义函数时只发生一次调用,在类实例化时发生一次。唯一的缺点是函数属性会消耗一点点额外的内存。
from types import FunctionType
class C:
def __init__(self):
for name,f in C.__dict__.iteritems():
if type(f) == FunctionType and hasattr(f, 'setup'):
self.instance_method()
def instance_method(self):
print('Method called')
def decorator(f):
setattr(f, 'setup', True)
return f
@decorator
def function(self):
pass
c = C()
c.function()
c.function()
关于python - 在函数装饰器中调用 Python 实例方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3371680/