Is there a problem with deep bone?

A 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 

Exit

 ['error msg'] 

Question

Why does this infer? I thought I cloned the error list before modifying it, and that they should not both refer to the same list?

+4
source share
2 answers

By setting dict fields to metaclass , you create a class attribute.

The __new__ method you __new__ run only once - when you create the class.

Update

You should manipulate attrs in __new__ like you, but name it something like _fields . Then create an __init__ method that executes deepcopy on the attribute called fields .

+2
source

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 deepcopy to BaseForm.__init__ instead, which is actually called every time an instance of MyForm is created.

0
source

Source: https://habr.com/ru/post/1315232/


All Articles