Class 装饰器 - class 字段的修改也改变了基础 class 中的值

Class decorator - modification of class field changes value in base class too

我写了一个带参数的 class 装饰器。此装饰器需要设置 class 字段的值 ID。我正在按照以下方式进行操作:

class Base:
    ID = "ID_Base"
    def __init__(self, n):
        self.n = n

    def func(self):
        pass

def Test(cnt):
    def createTest(className):
        class _Test(className):
            def __init__(self, n):
                className.__init__(self, n)

            def func(self):
                for n in range(cnt):
                    className.func(self)

        name = className.__name__ + "_Test"
        _Test.__name__ = name
        globals()[name] = _Test

        _Test.ID = className.ID + '_test'
        className.ID = ''
        return _Test

    return createTest

@Test(2)
class Derived(Base):
    pass

print(Base.ID)
print(Derived.ID)
print(Derived_Test.ID)

在函数 createTest 中,首先我从给定的 class 类型派生了 class 的定义,然后我修改 class 新名称 _Test class 并在当前模块中将其注册为全局 class,然后(在最后一个块中)我在 _Test class 中设置 ID 属性并在 ID 中清除 ID class 作为参数传递,return 新类型。我这样做是为了得到以下结果:

ID_Base

ID_Base_test

但是在 运行 之后我看到了这个:

ID_Base
ID_Base_test
ID_Base_test

为什么它修改 Derived class 的属性而不是 _Test 在装饰器中创建的属性?以及如何修复它?

我使用 Python 2.6.6 (Linux) 和 Python 3.4.1 (ActivePython on Windows) 进行了检查。

编辑:我也尝试在 _Test class 中设置 ID,如下所示,但得到了相同的结果:

def Test(cnt):
    def createTest(className):
        class _Test(className):
            ID = className.ID + '_test'

你从 print(Derived.ID) 得到 ID_Base_test 的原因是在装饰的末尾有一个隐式赋值,这使得 Derived 引用 class Derived_Test。下面的代码

@Test(2)
class Derived(Base):
    pass

有点等于

class Derived(Base):
    pass
Derived = Test(2)(Derived)

装饰后尝试print(Derived),你会得到__main__.Derived_Test

更新:请参阅 this wiki 了解更多说明。

A decorator is any callable Python object that is used to modify a function, method or class definition. A decorator is passed the original object being defined and returns a modified object, which is then bound to the name in the definition.