2015-12-11 63 views
0

这是一个基本的Python问题。我想用我自己的装饰师my_decorator来装饰@classmethod。原来@classmethod其实调用里面另一个@classmethod。调用此内部方法时出现问题,因为它取决于cls参数。如果我可以用Foo.boo()代替cls.boo()这样的电话,如果我的班级始终是Foo,那么这很好,但是当我编写继承自Foo的子类时,这显然不是一种选择。以下是我正在写的内容。装饰已经用@classmethod装饰的Python方法,它调用另一个@classmethod

def my_decorator(method): 
    def redefined_method(*args, **kwargs): 
     print('Starting decorator') 
     result = method(args, **kwargs) 
     return result 
    return redefined_method 

class Foo(object):   
    @classmethod 
    def boo(cls): 
     print('Running from Foo\'s boo') 

    @classmethod 
    @my_decorator 
    def bar(cls): 
     print('Running from Foo\'s bar') 
     ''' 
     Replacing the following line with 'Foo.boo()' 
     produces no errors when calling `Foo.bar()`, 
     but then we can't run Child's version of the boo method. 
     ''' 
     cls.boo() 

class Child(Foo): 
    @classmethod 
    def boo(cls): 
     print('Running from Child\'s version of boo') 

if __name__ == '__main__': 
    Foo.bar()  
    Child.bar() 

我期待以下输出。

Starting decorator 
Running from Foo's bar 
Running from Foo\'s boo 
Starting decorator 
Running from Foo's bar 
Running from Child\'s version of boo 

电流输出。

Starting decorator 
Running from Foo's bar 
Traceback (most recent call last): 
    File "C:\....\dec_example.py", line 29, in <module> 
    Foo.bar()  
    File "C:\....\dec_example.py", line 4, in redefined_method 
    method(args, **kwargs) 
    File "C:\....\dec_example.py", line 21, in bar 
    cls.boo() 
AttributeError: 'tuple' object has no attribute 'boo' 

我试图切换@classmethod@my_decorator顺序,但它仍然无法正常工作,并产生下列堆栈跟踪。

Starting decorator 
Traceback (most recent call last): 
    File "C:\....\dec_example.py", line 29, in <module> 
    Foo.bar()  
    File "C:\....\dec_example.py", line 4, in redefined_method 
    method(args, **kwargs) 
TypeError: 'classmethod' object is not callable 

回答

3

你忘了解压args

def my_decorator(method): 
    def redefined_method(*args, **kwargs): 
     print('Starting decorator') 
     method(args, **kwargs) 
     # here ^, no star! 
    return redefined_method 
+0

哦,那个工作。 – bourbaki4481472

+1

通常你也会返回'method'返回的值。有了这个版本,没有返回值是可能的。 –

+0

@TomKarzes,这是一个错字。很好的接收。 – bourbaki4481472