2012-07-31 79 views
17

我有一个类在他们的函数上有一个沉闷的重复模式,我想把这个模式变成一个装饰器。但问题是这个装饰器必须访问当前实例的一些属性,所以我想把它变成这个类中的一个方法。我遇到了一些问题。方法可以是同一类的另一种方法的装饰器吗?

所以,这是类似于我想要的东西:

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 
+1

请修复您的缩进。另请注意,您的代码不包含任何类方法。 – 2012-07-31 12:57:37

+0

您是否问过如何将“self”以外的* * *实例传递给'mydecorator',因为它装饰'somemethod'? – kojiro 2012-07-31 13:00:13

+0

糟糕。从vim复制并粘贴到浏览器有时候会很痛苦... – 2012-07-31 13:00:39

回答

11

装饰器只获取一个参数 - 装饰的函数或方法。它不会像self参数那样传递实例 - 在调用装饰器时,甚至不创建类,更不用说类的实例了。该实例将作为第一个参数传递给装饰函数,因此您应该在参数列表call()中包含self作为第一个参数。

我没有看到在类作用域中包含装饰器的必要性。你可以做到这一点,但你也可以在模块范围内使用它。

+0

该死的,这很明显。装饰器只接收该方法并返回一个修改后的方法。该方法是必须处理实例的人...该死的。非常明显。 – 2012-07-31 13:07:07

+0

如果您的装饰器需要使用类成员,该怎么办?或者这只是一个糟糕的主意/模式? – aaronlevin 2012-07-31 14:07:40

+0

@weirdcanada:由于该类在调用装饰器时尚未创建,因此无法以普通方式访问其成员。你可以做一些黑客来解决这个问题(比如将'locals()'作为参数传递给装饰器),但它们不是很明显,我想不出一个好的理由来做到这一点。 – 2012-07-31 14:19:00

相关问题