ProgrammierungBackend Python Entwickler

Was ist der Unterschied zwischen shallow copy und einfacher Zuweisung einer Variablen? Wie funktioniert copy.copy() in Bezug auf verschachtelte Datenstrukturen (Listen in Listen)?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort

Die Zuweisung einer Variablen (z.B. a = b) in Python kopiert nicht das Objekt selbst, sondern erstellt nur einen neuen Namen (Verweis) auf das bestehende Objekt. Änderungen über einen Namen sind auch über den anderen sichtbar, wenn es sich um ein veränderbares Objekt handelt.

Shallow copy (flaches Kopieren), z.B. über copy.copy(obj) oder mit einem Slice [:] für Listen, erstellt ein neues Objekt auf oberster Ebene, aber die darin enthaltenen Objekte werden per Referenz kopiert (d.h. beide Strukturen "zeigen" auf die gleichen Untercontainer). Wenn die inneren Objekte geändert werden, sind die Änderungen durch beide Objekte sichtbar.

Beispiel:

import copy lst1 = [[1,2], [3,4]] lst2 = copy.copy(lst1) # oder lst1[:] lst1[0][0] = 100 print(lst2) # [[100, 2], [3, 4]]

lst2 ist eine neue Liste, aber ihr erstes Element ist dieselbe verschachtelte Liste.

Fangfrage

Frage: Was ist der Unterschied zwischen lst2 = lst1[:] und lst2 = copy.copy(lst1)?

Antwort: In der Praxis gibt es für gewöhnliche (einzelne) Listen keine Unterschiede – beide Methoden erstellen eine flache Kopie der Liste. Für benutzerdefinierte Containerklassen kann jedoch ein unterschiedliches Verhalten auftreten (z.B. wenn die Methode __copy__ implementiert wurde). Ebenso ist es sicherer, für andere Typen (dict, set usw.) das spezialisierte Modul copy zu verwenden.

import copy lst1 = [1, 2, 3] lst2 = lst1[:] lst3 = copy.copy(lst1) print(lst2 == lst3) # True

Beispiele für reale Fehler aufgrund von Unkenntnis der Feinheiten des Themas


Geschichte

In einem Projekt zur Verarbeitung von Konfigurationen duplizierte der Entwickler die Standardparameter durch Zuweisung params = default_params und stellte sich vor, dass er sie "isoliert" ändern könnte. Infolgedessen führten Änderungen in einer Kopie zu einem Kaskadeneffekt in allen Teilen der Anwendung, weil sie tatsächlich mit demselben Objekt arbeiteten.


Geschichte

Ein unerfahrener Programmierer verwendete eine flache Kopie der Liste zur Speicherung des Spielstands (game_states = states[:]). Bei einer verschachtelten Struktur (Listen von Figuren auf dem Feld) „übertrugen“ sich Änderungen innerhalb eines Zustands in andere, was die Geschichte der Rücksetzungen und Wiederholungen der Züge zerstörte.


Geschichte

Bei dem Versuch, Daten in einer OOP-Anwendung zu klonen, gab es die Wahl zwischen einem Slice und copy.copy(). Aber in der Struktur gab es eine eigene Klasse mit ihrer eigenen Kopiermethode, die nur bei der Verwendung von copy.copy() berücksichtigt wurde. Der Slice ignorierte die Logik der Objekterstellung, und es traten unerwartete Bugs auf.