装饰器中的无限递归(类似乎从它自身继承)

时间:2015-09-08 16:11:36

标签: python python-2.7 recursion

我在装饰类中看到无限递归:

def my_decorator():
    def class_decorator(cls):
        class NewClass(cls):
            @classmethod
            def func(cls):
                print "decorator"
                super(NewClass, cls).func()

        return NewClass
    return class_decorator

class B(object):
    @classmethod
    def func(cls):
        print "Root"

@my_decorator()
class A(B):
    @classmethod
    def func(cls):
        print "func"
        super(A, cls).func()


x = A()    
x.func()

输出:

decorator
func
func
func
func
... <lots of 'func'> ...
lots of these:
  File "test.py", line 22, in func
    super(A, cls).func()
  File "test.py", line 22, in func
    super(A, cls).func()
  File "test.py", line 22, in func
    super(A, cls).func()
RuntimeError: maximum recursion depth exceeded while calling a Python object

没有装饰器,它返回:

func
Root

......正如所料。

发生了什么?

2 个答案:

答案 0 :(得分:2)

在您装饰原始A后,相当于:

A = my_decorator()(A)

名称A是指新创建的NewClass,它还会继承原始A原始A。因此super(A, cls).func始终解析为super(NewClass, cls).func,即A.func

展开装饰器并将结果分配给不同的名称,您将获得正确的行为:

X = my_decorator()(A)
x = X()
x.func()

给出:

decorator
func
Root

答案 1 :(得分:0)

这样的代码:

@my_decorator()
class A(B):
# ...

在语义上与:

相同
A = my_decorator(A)

(根据PEP 3129

这意味着名称为A的符号,通常会将Type值设置为“A类”,实际上重新定义是从my_decorator返回的任何内容,类型为NewClass

所以在你打电话的时候

 super(A, cls).func()

A实际上是指NewClass(和cls一样),导致调用相同的方法。