2010-06-09 110 views
3

我尝试定义类装饰器。我在装饰课上用__init__方法有问题。如果__init__方法调用superRuntimeError最大递归深度超出被引发。Python类装饰器和超过最大递归深度

代码示例:

def decorate(cls): 
    class NewClass(cls): pass 
    return NewClass 

@decorate 
class Foo(object): 
    def __init__(self, *args, **kwargs): 
     super(Foo, self).__init__(*args, **kwargs) 

我在做什么错?

感谢,米哈尔

编辑1

感谢Mike布尔人回答我意识到,正确的问题是,我该怎么办才达到该超(美孚,个体经营)指向正确的类。

我也有两个限制。我想调用Foo.__init__方法,我不能更改Foo类定义。

编辑2

我已经解决了这个问题。我修改装饰函数体。我不回新班。而不是我包装原始类的方法。

+0

可能重复(http://stackoverflow.com/questions/2542747/class-decorators-inheritance-super-and-maximum-recursion) – 2010-06-09 13:23:50

+0

如何将装饰器应用于Foo类,但无法更改其定义? – 2010-06-09 17:31:06

+0

我正在写ajax验证django应用程序。它应该是通用的,并且不需要对表单类定义进行更改。 – 2010-06-09 18:25:14

回答

4

您需要覆盖NewClass.__init__以防止递归,因为NewClass.__init__Foo.__init__并且它一直在调用自己。

def decorate(cls): 
    class NewClass(cls): 
     def __init__(self): 
      pass 
    return NewClass 

新的想法:

如何不继承呢?也许猴子补丁是你的朋友?

def decorate(cls): 
    old_do_something = cls.do_something 
    def new_do_something(self): 
     print "decorated", 
     old_do_something(self) 

    cls.do_something = new_do_something 
    return cls 

@decorate 
class Foo(object): 
    def __init__(self, *args, **kwargs): 
     super(Foo, self).__init__(*args, **kwargs) 

    def do_something(self): 
     print "Foo" 

f = Foo() 
f.do_something() 
[类装修,继承,超级(),和最大递归]的
+0

好吧,但我想执行Foo .__ init__方法。我也不能编辑Foo类的定义。 – 2010-06-09 16:02:45

+0

是的,它工作正常。 – 2010-06-11 07:36:53

+0

希望“不是子类”是一个单独的答案,所以我可以在修改实际类的时候对其进行+1修改(这在很多情况下不起作用)。 – claytond 2017-09-05 20:40:20

3

请记住,一个装饰简直是语法糖:

>>> Foo = decorate(Foo) 

因此,在这种情况下,名富其实是指NewClass类。在Foo.__init__方法中,您实际上是要求NewClass的超级__init__,即Foo.__init__(这是当前正在运行的)。

因此,你的Foo.__init__不断收到它自己的__init__来调用,你最终在一个无限递归。