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']
为什么输出?我以为我在修改它之前克隆了错误列表,并且它们不应该同时引用相同的列表?
答案 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
实例化时,实际 就会被调用。