1

我有一个类列表,我正在尝试动态创建另一个类列表,这样每个类都有一个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)

4

1 回答 1

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函数的本地命名空间中查找,并且只有一个值绑定到该名称。

于 2013-05-08T12:40:03.387 回答