我有一个类列表,我正在尝试动态创建另一个类列表,这样每个类都有一个classmethod
,它从原始列表中创建一个类的子实例。登记/>
问题是所有方法最终返回同一个类的实例(最后一个创建的实例)。
以下是我的代码的最小化版本:
class C1():
var = 1
class C2():
var = 2
parents = (C1, C2)
children = []
wrappers = []
for c in parents:
class ChildClass(c):
pass
children.append(ChildClass())
class Wrapper():
@classmethod
def method(cls):
cls.wrapped = ChildClass()
wrappers.append(Wrapper)
print(list(child.var for child in children))
for wrapper in wrappers:
wrapper.method()
print(list(wrapper.wrapped.var for wrapper in wrappers))
输出:
[1, 2]
[2, 2]
您可以看到children
列表包含不同的实例,而classmethod
在两种情况下都会创建C2
子项的实例。
如何修复我的代码,以便每个classmethod
创建一个正确类的实例?
(我正在使用python 2.7.4)
答案 0 :(得分:2)
ChildClass
中的Wrapper.method()
引用是一个自由变量,意味着在定义方法时,Wrapper.method()
被调用时将解析
当您调用该方法时,名称ChildClass
将引用您创建的最后一个类。
您需要提供仅ChildClass
具有一个明确值的范围,或者在定义时绑定引用。后者可以使用函数参数default:
class Wrapper():
@classmethod
def method(cls, child_class=ChildClass):
cls.wrapped = child_class()
您还可以使用函数作用域将引用绑定到该作用域中的局部变量:
def createClasses(parent):
class ChildClass(parent):
pass
class Wrapper():
@classmethod
def method(cls):
cls.wrapped = ChildClass()
return ChildClass, Wrapper
for c in parents:
child, wrapper = createClasses(c)
children.append(child)
wrappers.append(wrapper)
这里,当Wrapper.method
引用ChildClass
时,它将在createClasses
函数的本地命名空间中查找,并且只会有一个值绑定到那个名字。