我有一个班级,其功能上有一个沉闷的重复模式,我想把这个模式变成一个装饰器。但问题是这个装饰器必须访问当前实例的一些属性,所以我想把它变成这个类中的一个方法。我对此有一些问题。
所以,这类似于我想要的:
class DullRepetitiveClass:
def __init__(self, nicevariable):
self.nicevariable = nicevariable
def mydecorator(self, myfunction):
def call(*args, **kwargs):
print "Hi! The value of nicevariable is %s"%(self.nicevariable,)
return myfunction(*args, **kwargs)
return call
@mydecorator #Here, comment (1) below.
def somemethod(self, x):
return x + 1
(1) 问题来了。我想用
DullRepetitiveClass.mydecorator
方法装饰somemethod
方法。但是我不知道如何使用当前实例中的方法作为装饰器。
有简单的方法吗?
编辑:好的,答案很明显。正如 Sven 在下面所说的,装饰器本身只是转换方法。方法本身应该处理与实例有关的所有事情:
def mydecorator(method):
def call(self, *args, **kwargs):
print "Hi! The value of nicevariable is %s"%(self.nicevariable,)
return method(self, *args, **kwargs)
return call
class DullRepetitiveClass:
def __init__(self, nicevariable):
self.nicevariable = nicevariable
@mydecorator
def somemethod(self, x):
return x + 1
装饰器只有一个参数——它装饰的函数或方法。它没有将实例作为
self
参数传递——在调用装饰器的那一刻,甚至还没有创建类,更不用说类的实例了。该实例将作为第一个参数传递给装饰函数,因此您应该将 self
作为第一个参数包含在 call()
. 的参数列表中
我不认为有必要在类范围内包含装饰器。你可以这样做,但你也可以在模块范围内使用它。
装饰器必须在对象中设置属性的情况,例如为
nicevariable
添加一个字符,
您可以自己设置装饰器,而不是依赖 Python 通过 @
运算符 提供的语法糖
class DullRepetitiveClass:
def __init__(self, nicevariable):
self.nicevariable = nicevariable
self.somemethod = self.mydecorator(self.somemethod)
def mydecorator(self, myfunction):
def call(*args, **kwargs):
self.nicevariable += 'X'
print "Hi! The value of nicevariable is now %s"%(self.nicevariable,)
return myfunction(*args, **kwargs)
return call
def somemethod(self, x):
return x + 1
注意
call
如何在其参数中没有获得 self
(如果您想检查,打印出 args
),但是对 myfunction(*args, **kwargs)
的调用确实注入了它,所以 somemethod
得到了它。
另一方面,如果你把装饰器放在类之外,你仍然可以访问对象:
def mydecorator(myfunction):
def call(self, *args, **kwargs):
self.nicevariable += 'X'
print "Hi! The value of nicevariable is now %s"%(self.nicevariable,)
return myfunction(self, *args, **kwargs)
return call
class DullRepetitiveClass:
def __init__(self, nicevariable):
self.nicevariable = nicevariable
@mydecorator
def somemethod(self, x):
return x + 1
在这种情况下
self
call
函数接收self
就个人而言,我更喜欢将装饰器包含在类中,因为它对其特定属性进行操作并且看起来更独立。