我用参数写了一个类装饰器。此装饰器需要设置类字段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
中,我首先定义了从给定类类型派生的类,然后修改新_Test
类的类名,并在当前模块中将其注册为全局类,然后(在最后一个块中) )我在ID
类中设置_Test
属性,并在作为参数传递的类中清除ID
,并返回新类型。我这样做是为了获得以下结果:
ID_Base
ID_Base_test
然而,在运行之后我看到了这个:
ID_Base
ID_Base_test
ID_Base_test
为什么它会修改Derived
类的属性而不是修饰器中创建的_Test
?以及如何解决它?
我使用Python 2.6.6(Linux)和Python 3.4.1(Windows上的ActivePython)进行了检查。
编辑:我也尝试在_Test
类中设置ID,如下所示,但结果相同:
def Test(cnt):
def createTest(className):
class _Test(className):
ID = className.ID + '_test'
答案 0 :(得分:2)
您从ID_Base_test
获得print(Derived.ID)
的原因是在装饰结束时存在隐式分配,这使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了解更多解释。
装饰器是任何可调用的Python对象,用于修改函数,方法或类定义。装饰器传递给定义的原始对象,并返回一个修改过的对象,然后绑定到定义中的名称。