Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
modul:m323:learningunits:lu02:byreferenceinclasses [2024/08/28 09:11] kmaurizimodul:m323:learningunits:lu02:byreferenceinclasses [2024/08/28 09:42] (aktuell) kmaurizi
Zeile 20: Zeile 20:
 </code> </code>
  
-Diese Dataclass Person hat zwei Attribute: ''name'' und ''age''.+Diese Dataclass ''Person'' hat zwei Attribute: ''name'' und ''age''.
  
 ===== By Reference bei Dataclasses ===== ===== By Reference bei Dataclasses =====
Zeile 42: Zeile 42:
     person.age += 1     person.age += 1
  
-if name == 'main':+if __name__ == '__main__':
     p = Person(name='Alice', age=30)     p = Person(name='Alice', age=30)
-    print(f'Vor der Änderung: {p}') # Output: Vor der Änderung: Person(name='Alice', age=30)+    print(f'Vor der Änderung: {p}' # Output: Vor der Änderung: Person(name='Alice', age=30)
     birthday(p)     birthday(p)
-    print(f'Nach der Änderung: {p}') # Output: Nach der Änderung: Person(name='Alice', age=31)+    print(f'Nach der Änderung: {p}' # Output: Nach der Änderung: Person(name='Alice', age=31)
 </code> </code>
  
-In diesem Beispiel wird die Instanz der Dataclass Person an die Funktion ''birthday()'' übergeben. Da Objekte ''By Reference'' übergeben werden, wird das Attribut age der Originalinstanz ''p'' direkt in der Funktion verändert.+In diesem Beispiel wird die Instanz der Dataclass ''Person'' an die Funktion ''birthday()'' übergeben. Da Objekte ''By Reference'' übergeben werden, wird das Attribut ''age'' der Originalinstanz ''p'' direkt in der Funktion verändert.
  
 ===== Mutable und Immutable Attribute in Dataclasses ===== ===== Mutable und Immutable Attribute in Dataclasses =====
Zeile 55: Zeile 55:
 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 ''By Reference'' übergeben. 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 ''By Reference'' übergeben.
  
-==== Beispiel: Mutable Attribute in Dataclasses ====+==== Problem: Mutable Default Values ==== 
 + 
 +Ein häufiges Problem bei der Verwendung von mutable Objekten (wie Listen) in Dataclasses ist, dass alle Instanzen der Dataclass denselben Standardwert teilen können, wenn dieser direkt als Default-Wert gesetzt wird. Dies kann zu unerwartetem Verhalten führen. 
 + 
 +<code python> 
 +from dataclasses import dataclass 
 + 
 +@dataclass 
 +class Student: 
 +    name: str 
 +    grades: list [] 
 + 
 +# Problem: Alle Instanzen teilen sich dieselbe Liste. 
 +if __name__ == '__main__': 
 +    student1 Student(name='Alice'
 +    student2 = Student(name='Bob'
 + 
 +    student1.grades.append(90) 
 +    print(student2.grades)  # Output: [90] - Dies ist wahrscheinlich nicht das gewünschte Verhalten 
 +</code> 
 + 
 +In diesem Beispiel teilen sich alle Instanzen der Dataclass ''Student'' die gleiche Liste ''grades'', da der Standardwert direkt gesetzt wurde. Wenn eine Note zu einer Instanz hinzugefügt wird, beeinflusst dies auch alle anderen Instanzen. 
 + 
 +==== Lösung: Verwendung von `field(default_factory=list)` ==== 
 + 
 +Um dieses Problem zu lösen, verwendet man in Dataclasses für mutable Standardwerte wie Listen die Funktion `field` mit dem Parameter `default_factory`. Dadurch wird sichergestellt, dass jede Instanz ihre eigene Liste erhält.
  
 <code python> <code python>
 from dataclasses import dataclass, field from dataclasses import dataclass, field
-from typing import List 
  
 @dataclass @dataclass
 class Student: class Student:
     name: str     name: str
-    grades: List[int] = field(default_factory=list)+    grades: list = field(default_factory=list)
  
-def add_grade(student: Student, grade: int)+if __name__ == '__main__'
-    """ +    student1 = Student(name='Alice') 
-    Adds a grade to the student's grade list. +    student2 = Student(name='Bob')
-    """ +
-    student.grades.append(grade)+
  
-if name == 'main': +    student1.grades.append(90) 
-    s = Student(name='Bob'+    print(student2.grades)  # Output: [] - Jede Instanz hat ihre eigene, unabhängige Liste
-    print(f'Vor der Änderung: {s.grades}') # Output: Vor der Änderung: [] +
-    add_grade(s, 90) +
-    print(f'Nach der Änderung: {s.grades}') # Output: Nach der Änderung: [90]+
 </code> </code>
  
-In diesem Beispiel wird die Liste grades (ein mutable Attributinnerhalb der Funktion ''add_grade'' verändert. Da das Objekt Student by reference übergeben wirdwird die Original-Liste grades modifiziert.+Durch die Verwendung von `field(default_factory=list)` wird sichergestellt, dass jede Instanz von ''Student'' eine eigene Liste erhältund Änderungen an einer Instanz wirken sich nicht auf andere Instanzen aus.
  
 ===== Immutable Dataclasses ===== ===== Immutable Dataclasses =====
Zeile 96: Zeile 115:
 </code> </code>
  
-In diesem Fall ist die Dataclass ImmutablePerson unveränderlich, was bedeutet, dass jedes Attribut, sobald es gesetzt ist, nicht mehr geändert werden kann. Jeder Versuch, das Attribut ''age'' oder ''name'' zu ändern, führt zu einem Fehler.+In diesem Fall ist die Dataclass ''ImmutablePerson'' unveränderlich, was bedeutet, dass jedes Attribut, sobald es gesetzt ist, nicht mehr geändert werden kann. Jeder Versuch, das Attribut ''age'' oder ''name'' zu ändern, führt zu einem Fehler.
  
 ==== Beispiel: Anwendung einer frozen Dataclass ==== ==== Beispiel: Anwendung einer frozen Dataclass ====
Zeile 114: Zeile 133:
     return Person(name=person.name, age=person.age + 1)     return Person(name=person.name, age=person.age + 1)
  
-if name == 'main':+if __name__ == '__main__':
     p = Person(name='Alice', age=30)     p = Person(name='Alice', age=30)
-    print(f'Vor der Änderung: {p}') # Output: Vor der Änderung: Person(name='Alice', age=30)+    print(f'Vor der Änderung: {p}' # Output: Vor der Änderung: Person(name='Alice', age=30)
     new_p = birthday(p)     new_p = birthday(p)
-    print(f'Nach der Änderung: {p}') # Output: Nach der Änderung: Person(name='Alice', age=30) +    print(f'Nach der Änderung: {p}' # Output: Nach der Änderung: Person(name='Alice', age=30) 
-    print(f'Neue Instanz: {new_p}') # Output: Neue Instanz: Person(name='Alice', age=31)+    print(f'Neue Instanz: {new_p}' # Output: Neue Instanz: Person(name='Alice', age=31)
 </code> </code>
  
Zeile 132: Zeile 151:
   * **Vorhersehbarkeit:** Pure functions sind leichter zu verstehen und zu testen, da das Ergebnis nur von den Eingabewerten abhängt.   * **Vorhersehbarkeit:** Pure functions sind leichter zu verstehen und zu testen, da das Ergebnis nur von den Eingabewerten abhängt.
   * **Immutable Data:** Die Verwendung von immutable Datenstrukturen verhindert unbeabsichtigte Modifikationen und erleichtert die Parallelisierung von Programmen.   * **Immutable Data:** Die Verwendung von immutable Datenstrukturen verhindert unbeabsichtigte Modifikationen und erleichtert die Parallelisierung von Programmen.
 +
 Dieses Vorgehen ist besonders nützlich in Szenarien, in denen Datenintegrität und Vorhersagbarkeit des Programmverhaltens von hoher Bedeutung sind. Dieses Vorgehen ist besonders nützlich in Szenarien, in denen Datenintegrität und Vorhersagbarkeit des Programmverhaltens von hoher Bedeutung sind.
  
 ===== Zusammenfassung ===== ===== Zusammenfassung =====
  
-In Python werden Objekte, einschließlich Dataclasses, immer ''By Reference'' übergeben. Änderungen an den Attributen eines Objekts innerhalb einer Funktion wirken sich direkt auf das Originalobjekt aus. Um ungewollte Änderungen zu vermeiden, kann eine Dataclass als ''frozen'' deklariert werden, was sie unveränderlich macht und vor unbeabsichtigten Modifikationen schützt.+In Python werden Objekte, einschließlich Dataclasses, immer ''By Reference'' übergeben. Änderungen an den Attributen eines Objekts innerhalb einer Funktion wirken sich direkt auf das Originalobjekt aus. Um ungewollte Änderungen zu vermeiden, kann eine Dataclass als ''frozen'' deklariert werden, was sie unveränderlich macht und vor unbeabsichtigten Modifikationen schützt. Zusätzlich ist es wichtig, bei der Verwendung von mutable Default-Werten, wie Listen, darauf zu achten, dass jede Instanz ihre eigene unabhängige Kopie erhält, indem `field(default_factory=list)` verwendet wird.
  
 <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 ''frozen'' Dataclasses, um unbeabsichtigte Änderungen zu verhindern.+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 ''frozen'' Dataclasses oder `field(default_factory=list)`, um unbeabsichtigte Änderungen zu verhindern.
 </WRAP> </WRAP>
 +
  • modul/m323/learningunits/lu02/byreferenceinclasses.1724829086.txt.gz
  • Zuletzt geändert: 2024/08/28 09:11
  • von kmaurizi