如何使用类的一个实例变量作为在Python的方法装饰的说法?
题
如何使用一个类的实例变量作为在Python的方法装饰的参数? 下面是一个小例子,显示了我想要做的事。作为装饰功能没有访问参考实例,我不知道如何访问从装饰参考它显然失败。
def decorator1(arg1):
def wrapper(function):
print "decorator argument: %s" % arg1
return function
return wrapper
class Foo(object):
def __init__(self, arg1):
self.var1 = arg1
@decorator1(self.var1)
def method1(self):
print "method1"
foo = Foo("abc")
foo.method1()
解决方案
这不会工作;装饰器中的类创建时间,创建一个实例之前,其是所谓的长(如果有史以来发生)。所以,如果你的“装饰”所需要的情况下,你必须做的“装饰”在实例化时:
def get_decorator(arg1):
def my_decorator(function):
print "get_decorator argument: %s" % arg1
return function
return my_decorator
class Foo(object):
def __init__(self, arg1):
self.var1 = arg1
self.method1 = get_decorator(self.var1)(self.method1)
def method1(self):
print "method1"
foo = Foo("abc")
foo.method1()
请注意,根据它们的意义,我改变功能名称;实际的“装饰”,即该(潜在地)修改的方法中的功能,是在wrapper
你的情况下,不decorator1
。
其他提示
您“整经机”功能实际上是一个装饰,而不是一个整经。您的“decorator1”功能是一个装饰构造。如果你想有机会获得self.var1在运行时,你必须做出一个整经机没有装饰:
def decorator(function):
def wrapper(self,*args,**kwargs):
print "Doing something with self.var1==%s" % self.var1
return function(self,*args,**kwargs)
return wrapper
class Foo(object):
def __init__(self, arg1):
self.var1 = arg1
@decorator
def method1(self):
print "method1"
foo = Foo("abc")
foo.method1()
如果你想有更多的普通装饰,这是更好的主意来声明一个类调用:
class decorator:
def __init__(self,varname):
self.varname = varname
def __call__(self,function):
varname=self.varname
def wrapper(self,*args,**kwargs):
print "Doing something with self.%s==%s" % (varname,getattr(self,varname))
return function(self,*args,**kwargs)
return wrapper
使用:
@decorator("var1")
被定义的类时,执行所述的装饰机,这样就可以不一个实例变量传递给它。
下面就是我们用来做这在往日。
class Foo(object):
def __init__(self, arg1):
self.var1 = arg1
def method1(self):
self.lock()
try:
self.do_method1()
except Exception:
pass # Might want to log this
finally:
self.unlock()
def do_method1(self):
print "method1"
def lock(self):
print "locking: %s" % self.arg1
def unlock(self):
print "unlocking: %s" % self.arg1
现在,子类只需要O强制do_method1
获得“包装”的好处。做旧的方式,没有任何with
声明。
是的,这是啰嗦。然而,它不涉及任何魔法,要么。
不隶属于 StackOverflow