4

ソース

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

質問

なぜそれを出力するのですか?エラーリストを変更する前に複製したのですが、両方が同じリストを参照するべきではないと思いましたか?

4

2 に答える 2

2

にを設定するdict fieldsmetaclass、クラス属性が作成されます。

定義した__new__メソッドは、クラスの作成時に1回だけ実行されます。

アップデート

自分と同じように操作する必要attrs__new__ありますが、のような名前を付けてください_fields。次に、呼び出された__init__に対してを実行するメソッドを作成します。deepcopyattributefields

于 2010-07-09T18:22:35.153 に答える
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__、実際にMyFormaがインスタンス化されるたびに呼び出されます。

于 2010-07-09T19:09:08.100 に答える