深度复印问题?

时间:2010-07-09 18:08:40

标签: python deep-copy

来源

from copy import deepcopy

class Field(object):
    def __init__(self):
        self.errors = []

class BaseForm(object):
    pass

class MetaForm(type):
    def __new__(cls, name, bases, attrs):
        attrs['fields'] = dict([(name, deepcopy(attrs.pop(name))) for name, obj in attrs.items() if isinstance(obj, Field)])
        return type.__new__(cls, name, bases, attrs)

class Form(BaseForm):
    __metaclass__ = MetaForm

class MyForm(Form):
    field1 = Field()

f1 = MyForm()
f1.fields['field1'].errors += ['error msg']

f2 = MyForm()
print f2.fields['field1'].errors

输出

['error msg']

问题

为什么输出?我以为我在修改它之前克隆了错误列表,并且它们不应该同时引用相同的列表?

2 个答案:

答案 0 :(得分:2)

通过在dict中设置fields metaclass,您将创建一个类属性。

您定义的__new__方法只运行一次 - 在类创建时。

<强>更新

您应该像attrs一样操纵__new__,但请将其命名为_fields。然后创建一个__init__方法,在deepcopy attribute fields中执行{{1}}。

答案 1 :(得分:0)

更明确的解决方案:

from copy import deepcopy

class Field(object):
    def __init__(self):
        self.errors = []

class BaseForm(object):
    def __init__(self):
        self.fields = deepcopy(self.fields)

class MetaForm(type):
    def __new__(cls, name, bases, attrs):
        attrs['fields'] = dict([(name, attrs.pop(name)) for name, obj in attrs.items() if isinstance(obj, Field)])
        return type.__new__(cls, name, bases, attrs)

class Form(BaseForm):
    __metaclass__ = MetaForm

class MyForm(Form):
    field1 = Field()

f1 = MyForm()
f1.fields['field1'].errors += ['error msg']

f2 = MyForm()
print f2.fields['field1'].errors

只需将deepcopy移到BaseForm.__init__,每次MyForm实例化时,实际 就会被调用。