Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| Beide Seiten der vorigen Revision Vorhergehende Überarbeitung | |||
| modul:m323:learningunits:lu02:byreferenceinclasses [2026/08/18 10:19] – Kompetenz-Tags auf neue Kompetenzmatrix ZH gesetzt admin | modul:m323:learningunits:lu02:byreferenceinclasses [2026/08/25 09:14] (aktuell) – Korrektur mutable Defaults (Code warf ValueError) + Animation eingebunden admin | ||
|---|---|---|---|
| Zeile 4: | Zeile 4: | ||
| In Python werden Objekte, einschließlich Dataclasses, | In Python werden Objekte, einschließlich Dataclasses, | ||
| + | |||
| + | ===== Animation: Objekte, frozen und Standardwerte ===== | ||
| + | |||
| + | Die Animation zeigt drei Abläufe Schritt für Schritt. Tab 1 und 2 gehören zu den Beispielen weiter unten; Tab 3 zeigt, was bei einem veränderbaren Standardwert passiert – und damit den Grund, weshalb Dataclasses solche Standardwerte gar nicht erst zulassen. | ||
| + | |||
| + | {{url> | ||
| ===== Dataclasses ===== | ===== Dataclasses ===== | ||
| Zeile 55: | Zeile 61: | ||
| Python-Dataclasses können sowohl mutable als auch immutable Attribute enthalten. Unabhängig davon, ob die Attribute mutable oder immutable sind, wird die Dataclass selbst immer '' | Python-Dataclasses können sowohl mutable als auch immutable Attribute enthalten. Unabhängig davon, ob die Attribute mutable oder immutable sind, wird die Dataclass selbst immer '' | ||
| - | ==== Problem: | + | ==== Mutable |
| - | Ein häufiges Problem bei der Verwendung von mutable Objekten (wie Listen) in Dataclasses ist, dass alle Instanzen der Dataclass denselben | + | Es liegt nahe, einem Listen-Attribut einfach eine leere Liste als Standardwert zu geben: |
| <code python> | <code python> | ||
| Zeile 65: | Zeile 71: | ||
| class Student: | class Student: | ||
| name: str | name: str | ||
| - | grades: list = [] | + | grades: list = [] # ValueError! |
| + | </ | ||
| - | # Problem: Alle Instanzen teilen | + | Dieser Code lässt |
| - | if __name__ == ' | + | |
| - | student1 = Student(name=' | + | |
| - | student2 = Student(name=' | + | |
| - | student1.grades.append(90) | + | < |
| - | print(student2.grades) # Output: [90] - Dies ist wahrscheinlich | + | ValueError: mutable default <class ' |
| + | </ | ||
| + | |||
| + | Der Grund: Ein Standardwert wird **einmalig** ausgewertet – nämlich dann, wenn die Klasse bzw. die Funktion definiert wird, und nicht bei jeder Instanzierung. Alle Instanzen würden sich also dieselbe Liste teilen. Weil das fast nie gewollt ist, verbieten Dataclasses solche Standardwerte von vornherein. | ||
| + | |||
| + | <WRAP center round important 90%> | ||
| + | **Bei normalen Funktionen greift dieser Schutz nicht!** Dort ist derselbe Fehler erlaubt – und still: | ||
| + | |||
| + | <code python> | ||
| + | def add_grade(grade, | ||
| + | | ||
| + | | ||
| + | |||
| + | print(add_grade(90)) # Output: [90] | ||
| + | print(add_grade(80)) | ||
| </ | </ | ||
| - | In diesem Beispiel teilen sich alle Instanzen | + | Die Liste im Standardwert überlebt den Funktionsaufruf, |
| + | </ | ||
| ==== Lösung: Verwendung von `field(default_factory=list)` ==== | ==== Lösung: Verwendung von `field(default_factory=list)` ==== | ||
| - | Um dieses Problem zu lösen, | + | Für mutable Standardwerte |
| <code python> | <code python> | ||
| Zeile 97: | Zeile 116: | ||
| print(student2.grades) | print(student2.grades) | ||
| </ | </ | ||
| - | |||
| - | Durch die Verwendung von `field(default_factory=list)` wird sichergestellt, | ||
| ===== Immutable Dataclasses ===== | ===== Immutable Dataclasses ===== | ||
| Zeile 115: | Zeile 132: | ||
| </ | </ | ||
| - | In diesem Fall ist die Dataclass '' | + | In diesem Fall ist die Dataclass '' |
| + | |||
| + | < | ||
| + | FrozenInstanceError: | ||
| + | </ | ||
| ==== Beispiel: Anwendung einer frozen Dataclass ==== | ==== Beispiel: Anwendung einer frozen Dataclass ==== | ||
| Zeile 135: | Zeile 156: | ||
| if __name__ == ' | if __name__ == ' | ||
| p = Person(name=' | p = Person(name=' | ||
| - | print(f' | ||
| new_p = birthday(p) | new_p = birthday(p) | ||
| - | print(f' | + | print(f' |
| print(f' | print(f' | ||
| </ | </ | ||
| Zeile 156: | Zeile 176: | ||
| ===== Zusammenfassung ===== | ===== Zusammenfassung ===== | ||
| - | In Python werden Objekte, einschließlich Dataclasses, | + | In Python werden Objekte, einschließlich Dataclasses, |
| <WRAP center round tip 60%> | <WRAP center round tip 60%> | ||
| - | Tipp: Wenn Sie mutable Attribute in einer Dataclass verwenden, sollten Sie sorgfältig überlegen, ob die direkte Veränderung dieser Attribute innerhalb von Funktionen in Ihrem Programmdesign erwünscht ist. Verwenden Sie '' | + | Tipp: Wenn Sie mutable Attribute in einer Dataclass verwenden, sollten Sie sorgfältig überlegen, ob die direkte Veränderung dieser Attribute innerhalb von Funktionen in Ihrem Programmdesign erwünscht ist. Verwenden Sie '' |
| </ | </ | ||