2010-06-09 115 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__來調用,你最終在一個無限遞歸。