Chciałbym stworzyć kopię obiektu. Chcę, aby nowy obiekt posiadał wszystkie właściwości starego obiektu (wartości pól). Ale chcę mieć niezależne obiekty. Jeśli więc zmienię wartości pól nowego obiektu, stary obiekt nie powinien mieć na to wpływu.
199
Masz na myśli obiekt zmienny.
W Pythonie 3 listy uzyskują
copy
metodę (w 2 użyłbyś plasterka, aby wykonać kopię):Płytkie kopie
Płytkie kopie to tylko kopie najbardziej zewnętrznego pojemnika.
list.copy
jest płytką kopią:Nie dostajesz kopii wewnętrznych obiektów. Są tym samym obiektem - więc po zmutowaniu zmiana pojawia się w obu kontenerach.
Głębokie kopie
Głębokie kopie są rekurencyjnymi kopiami każdego obiektu wewnętrznego.
Zmiany nie są odzwierciedlane w oryginale, tylko w kopii.
Niezmienne przedmioty
Niezmienne obiekty zwykle nie muszą być kopiowane. W rzeczywistości, jeśli spróbujesz, Python da ci oryginalny obiekt:
Krotki nawet nie mają metody kopiowania, więc wypróbujmy to z kawałkiem:
Ale widzimy, że to ten sam obiekt:
Podobnie dla ciągów:
i dla frozensetów, mimo że mają
copy
metodę:Kiedy kopiować niezmienne obiekty
Niezmienne obiekty powinny zostać skopiowane, jeśli chcesz skopiować zmienny obiekt wewnętrzny.
Jak widać, gdy obiekt wewnętrzny kopii jest zmutowany, oryginał się nie zmienia.
Obiekty niestandardowe
Obiekty niestandardowe zwykle przechowują dane w
__dict__
atrybucie lub w__slots__
(kruchej strukturze pamięci).Aby utworzyć obiekt do kopiowania, zdefiniuj
__copy__
(dla płytkich kopii) i / lub__deepcopy__
(dla głębokich kopii).Zauważ, że
deepcopy
przechowuje słownik notatekid(original)
(lub numery identyfikacyjne) do kopii. Aby cieszyć się dobrym zachowaniem z rekurencyjnymi strukturami danych, upewnij się, że nie masz jeszcze kopii, a jeśli tak, zwróć ją.Zróbmy więc obiekt:
I
copy
wykonuje płytką kopię:A
deepcopy
teraz robi głęboką kopię:źródło
Płytka kopia z
copy.copy()
Głęboka kopia z
copy.deepcopy()
Dokumentacja: https://docs.python.org/3/library/copy.html
Testowane na Pythonie 3.6.5.
źródło
Uważam, że następujące elementy powinny działać z wieloma dobrze zachowanymi klasami w Pythonie:
(Oczywiście nie mówię tu o „głębokich kopiach”, które są inną historią i które mogą nie być zbyt jasnym pojęciem - jak głębokie są wystarczająco głębokie?)
Według moich testów w Pythonie 3 dla niezmiennych obiektów, takich jak krotki lub łańcuchy, zwraca ten sam obiekt (ponieważ nie ma potrzeby wykonywania płytkiej kopii niezmiennego obiektu), ale dla list lub słowników tworzy niezależną płytką kopię .
Oczywiście ta metoda działa tylko w przypadku klas, których konstruktory zachowują się odpowiednio. Możliwe przypadki użycia: wykonanie płytkiej kopii standardowej klasy kontenera Python.
źródło
__init__
metodzie. Pomyślałem więc, że ta metoda może być wystarczająca do pewnych celów. W każdym razie będę zainteresowany informacyjnymi komentarzami na temat tej sugestii.class Foo(object): def __init__(self, arg): super(Foo, self).__init__() self.arg = arg
podstawowymi. Jeśli tak, tofoo = Foo(3) bar = copy(foo) print(foo.arg) # 3 print(bar.arg) # <__main__.Foo object at ...>
znaczy, że twojacopy
funkcja jest zepsuta dla nawet najbardziej podstawowych klas. Znów jest to fajna sztuczka (stąd brak DV), ale nie odpowiedź.copy.copy
metoda robienia płytkich kopii, ale, być może, naiwnie, wydaje mi się, że zadaniem klasy powinno być zapewnienie „konstruktora płytkich kopii”. W takim przypadku dlaczego nie zapewnić tego samego kinf interfejsu dla niegodict
ilist
zrobić? Jeśli więc twoja klasa chce wziąć odpowiedzialność za kopiowanie swoich obiektów, dlaczego nie dodaćif isinstance(arg, type(self))
klauzuli__init__
?