开发者

Problem with deepcopy?

Source

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

Output

['error msg']

Question

Why does it output that? I thought I cloned the errors list before modifying it, and that they shouldn't both refer to the sa开发者_JS百科me list?


By setting the dict fields in the metaclass, you are creating a class attribute.

The __new__ method you defined is only run once -- on class creation.

Update

You should manipulate attrs in __new__ like you are, but name it something like _fields. Then create an __init__ method that performs a deepcopy into an attribute called fields.


A more explicit solution:

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

Just moved the deepcopy into BaseForm.__init__ instead, which actually is called each time a MyForm is instantiated.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜