Специфические атрибуты Deepcopy - PullRequest
0 голосов
/ 08 сентября 2018

Есть ли способ переопределить метод __copy__ для класса таким образом, что некоторые атрибуты копируются только в качестве ссылки , а другие атрибуты фактически скопировано

Чтобы уточнить, что я имею в виду, вот мое предположение о том, как это можно сделать. Рассмотрим класс Spam:

class Spam:
    def __init__(self, val=0, val2=0):
        self.eggs = []
        self.foo = []
        self.val = val
        self.val2 = val2

Предположим, мы хотели убедиться, что при вызове copy.copy (т.е. мелкой копии) для объекта Spam его атрибут eggs был глубоко скопирован в новый объект (так что что мутации в атрибуте исходного объекта не изменяют атрибут eggs копии). «Почему бы вам просто не deepcopy весь объект тогда?» - потому что, в отличие от eggs, мы хотим, чтобы атрибут foo копировался как ссылка (чтобы изменения в нем были виден всем копиям).

Тогда будет ли следующий подход верным?

    to_be_copied = ['eggs']  # States which attributes are to be copied

    def __copy__(self):
        copy_ = Spam()

        for attr in self.__dict__:
            if attr in Spam.to_be_copied:
                # Make an actual copy of the attribute
                copy_.__dict__[attr] = copy.copy(self.__dict__[attr])  
            else:
                # Copy reference
                copy_.__dict__[attr] = self.__dict__[attr]

        return copy_

1 Ответ

0 голосов
/ 08 сентября 2018

Это выглядит корректно, но если сделать set из to_be_copied, то при большом количестве атрибутов работа будет выполняться быстрее.

Кроме того, сократите с помощью троичного выражения + списка, как показано ниже

to_be_copied = {'eggs'}  # States which attributes are to be copied

def __copy__(self):
    copy_ = Spam()
    copy_.__dict__ = {attr:copy.copy(self.__dict__[attr]) if attr in Spam.to_be_copied else self.__dict__[attr] for attr in self.__dict__}
    return copy_

Недостаток переопределенного метода __copy__ dunder заключается в том, что он не соответствует принципу наименьшего удивления: пользователи copy.copy ожидают неглубокую копию, когда имеют дело с известными объектами, такими как list, которые вы предоставляете. пользовательская копия.

Может быть, было бы лучше вместо этого определить def copy(self): функцию (правильно задокументировано)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...