Я хотел бы создать копию объекта. Я хочу, чтобы новый объект обладал всеми свойствами старого объекта (значения полей). Но я хочу иметь независимые объекты. Итак, если я изменю значения полей нового объекта, на старый объект это не должно повлиять.
200
Вы имеете в виду изменчивый объект тогда.
В Python 3 списки получают
copy
метод (в 2 вы бы использовали фрагмент для создания копии):Мелкие копии
Мелкие копии - это всего лишь копии самого внешнего контейнера.
list.copy
это мелкая копия:Вы не получаете копию предметов интерьера. Это один и тот же объект - поэтому, когда они видоизменены, изменение обнаруживается в обоих контейнерах.
Глубокие копии
Глубокие копии - это рекурсивные копии каждого предмета интерьера.
Изменения не отражаются в оригинале, только в копии.
Неизменные предметы
Неизменяемые объекты обычно не нужно копировать. Фактически, если вы попытаетесь, Python просто выдаст вам оригинальный объект:
У кортежей даже нет метода копирования, поэтому давайте попробуем его с фрагментом:
Но мы видим, что это тот же объект:
Аналогично для строк:
и для фрозенце, хотя у них есть
copy
метод:Когда копировать неизменяемые объекты
Неизменяемые объекты должны быть скопированы, если вам нужно скопировать изменяемый внутренний объект.
Как мы видим, когда внутренний объект копии видоизменен, оригинал не изменяется.
Пользовательские объекты
Пользовательские объекты обычно хранят данные в
__dict__
атрибуте или в__slots__
структуре памяти, подобной кортежу.Чтобы создать копируемый объект, определите
__copy__
(для мелких копий) и / или__deepcopy__
(для глубоких копий).Обратите внимание, что
deepcopy
хранит словарь памяткиid(original)
(или идентификационные номера) для копий. Чтобы получить хорошее поведение с рекурсивными структурами данных, убедитесь, что вы еще не сделали копию, и, если она у вас есть, верните ее.Итак, давайте сделаем объект:
И
copy
делает мелкую копию:А
deepcopy
теперь делает глубокую копию:источник
Мелкая копия с
copy.copy()
Глубокая копия с
copy.deepcopy()
Документация: https://docs.python.org/3/library/copy.html
Проверено на Python 3.6.5.
источник
Я считаю, что следующее должно работать со многими классами в Python:
(Конечно, я не говорю здесь о «глубоких копиях», это отдельная история, и которая может быть не очень ясным понятием - насколько глубоко это глубоко?)
Согласно моим тестам на Python 3, для неизменяемых объектов, таких как кортежи или строки, он возвращает один и тот же объект (поскольку нет необходимости делать поверхностную копию неизменяемого объекта), но для списков или словарей он создает независимую поверхностную копию. ,
Конечно, этот метод работает только для классов, конструкторы которых ведут себя соответственно. Возможные варианты использования: создание мелкой копии стандартного контейнерного класса Python.
источник
__init__
методах. Итак, я подумал, что этот метод может быть достаточно хорош для определенных целей. В любом случае меня заинтересуют информативные комментарии по этому предложению.class Foo(object): def __init__(self, arg): super(Foo, self).__init__() self.arg = arg
Basic, как он есть. Если я делаю Этоfoo = Foo(3) bar = copy(foo) print(foo.arg) # 3 print(bar.arg) # <__main__.Foo object at ...>
означает, что вашаcopy
функция нарушена даже для самых базовых классов. Опять же, это аккуратный трюк (следовательно, нет DV), но не ответ.copy.copy
метод для создания мелких копий, но, возможно, наивно, мне кажется, что ответственность за обеспечение «конструктора мелкой копии» должна быть на классе. В таком случае, почему бы не предоставить такой же интерфейс к нему, какdict
иlist
делать? Итак, если ваш класс хочет взять на себя ответственность за копирование своих объектов, почему бы не добавить в негоif isinstance(arg, type(self))
предложение__init__
?