简体   繁体   English

Python类装饰器和超出的最大递归深度

[英]Python class decorator and maximum recursion depth exceeded

I try define class decorator. 我尝试定义类装饰器。 I have problem with __init__ method in decorated class. 我在装饰类中__init__方法的问题。 If __init__ method invokes super the RuntimeError maximum recursion depth exceeded is raised. 如果__init__方法调用super ,则会引发RuntimeError 超出的最大递归深度

Code example: 代码示例:

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

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

What am I doing wrong? 我究竟做错了什么?

Thanks, Michał 谢谢,Michał

Edit 1 编辑1

Thanks to Mike Boers answer I realized that correct question is what should I do to achive that super(Foo, self) point to proper class. 感谢Mike Boers的回答,我意识到正确的问题是我应该怎样做才能让超级(Foo,self)指向适当的阶级。

I have also two limitation. 我还有两个限制。 I want invoke Foo.__init__ method and I can't change Foo class definition. 我想调用Foo.__init__方法,我不能改变Foo类的定义。

Edit 2 编辑2

I have solved this problem. 我已经解决了这个问题。 I modify decorator function body. 我修改了装饰函数体。 I don't return new class. 我不回新课。 Instead of I wrap methods of orginal class. 而不是我包装原始类的方法。

You need to override NewClass.__init__ to prevent recursion, because NewClass.__init__ is Foo.__init__ and it keeps calling itself. 你需要覆盖NewClass.__init__以防止递归,因为NewClass.__init__Foo.__init__并且它一直在调用自己。

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

New idea: 新想法:

How about not subclassing it? 如何不进行子类化? Maybe monkey patching is your friend? 也许猴子补丁是你的朋友?

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()

Remember that a decorator is simply syntactic sugar for: 请记住,装饰器只是语法糖:

>>> Foo = decorate(Foo)

So in this case the name Foo actually refers to the NewClass class. 所以在这种情况下,名称Foo实际上是指NewClass类。 Within the Foo.__init__ method you are in fact asking for the super __init__ of NewClass , which is Foo.__init__ (which is what is currently running). Foo.__init__方法中,你实际上要求NewClass的超__init__ ,即Foo.__init__ (这是当前正在运行的)。

Thus, your Foo.__init__ keeps receiving its own __init__ to call, and you end up in an infinite recursion. 因此,你的Foo.__init__继续接收它自己的__init__来调用,你最终会进行无限递归。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM