【问题标题】:Problem with deepcopy?深拷贝有问题吗?
【发布时间】:2010-07-09 18:08:40
【问题描述】:

来源

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']

问题

为什么会这样输出?我以为我在修改之前克隆了错误列表,它们不应该都引用同一个列表?

【问题讨论】:

  • 看起来MetaForm.__new__ 只为MyForm 调用一次(为Form 调用一次)即使我已经构造了 twoMyForms。这是如何运作的?我的理解是每次构建时都需要调用它。我猜它在班级层面上运作?那么移动deepcopy 语句的最佳位置在哪里?

标签: python deep-copy


【解决方案1】:

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

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

更新

您应该像您一样在__new__ 中操作attrs,但将其命名为_fields。然后创建一个__init__ 方法,该方法将deepcopy 执行为一个名为fieldsattribute

【讨论】:

  • 啊.. 我对 __new__ 的工作原理有一个根本的误解。
  • __init__ 在哪个班级? BaseForm?因为MetaForm.__init__ 也只被调用一次,不是吗?
  • __init__ 用于Form
  • 嗯...Form 类是故意留空的,所以我将它填充到基础中。相同的差异。谢谢!
【解决方案2】:

更明确的解决方案:

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 时都会调用它

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-12
    • 1970-01-01
    • 2015-01-13
    • 2011-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多