EMZETT.
Login

Kurz: Zwei Werkzeuge machen Klassen im Alltag kürzer und sicherer: Dataclasses nehmen dir Routinecode ab, Properties kontrollieren den Zugriff auf Attribute.

Teil des Kurses Python

Kapitel 39 von 44 im Kurs Python. Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

Zwei Werkzeuge machen Klassen im Alltag kürzer und sicherer: Dataclasses nehmen dir Routinecode ab, Properties kontrollieren den Zugriff auf Attribute.

Dataclasses

Für Klassen, die vor allem Daten halten, schreibt man mit @dataclass nur noch die Felder. Python erzeugt __init__, __repr__ und __eq__ selbst:

from dataclasses import dataclass
 
@dataclass
class Person:
    name: str
    alter: int
    stadt: str = "Köln"
 
p = Person("Mia", 17)
print(p)
print(p == Person("Mia", 17))
p.alter += 1
print(p.alter)

Ausgabe:

Person(name='Mia', alter=17, stadt='Köln')
True
18

Nützliche Optionen

from dataclasses import dataclass, field, asdict, replace
 
@dataclass(frozen=True, order=True)
class Artikel:
    preis: float
    name: str = field(compare=False)
    tags: tuple = ()
 
a = Artikel(2.5, "Stift")
b = Artikel(1.0, "Heft")
print(sorted([a, b]))
print(asdict(a))
print(replace(a, preis=9.0))
try:
    a.preis = 3
except Exception as e:
    print(type(e).__name__)

Ausgabe:

[Artikel(preis=1.0, name='Heft', tags=()), Artikel(preis=2.5, name='Stift', tags=())]
{'preis': 2.5, 'name': 'Stift', 'tags': ()}
Artikel(preis=9.0, name='Stift', tags=())
FrozenInstanceError
OptionWirkung
frozen=Trueunveränderlich, auch hashbar
order=Trueerzeugt Vergleiche (<, >) über die Felder
field(default_factory=list)veränderlicher Standardwert pro Objekt
field(compare=False)Feld beim Vergleichen ignorieren

Achtung

Als Standardwert nie [] oder {} direkt verwenden, sondern field(default_factory=list). Sonst teilen sich alle Objekte dieselbe Liste.

Properties

Eine Property sieht von außen wie ein Attribut aus, ruft aber Code auf. So prüfst du Werte oder berechnest sie bei Bedarf:

class Temperatur:
    def __init__(self, celsius):
        self.celsius = celsius          # läuft durch den Setter
 
    @property
    def celsius(self):
        return self._celsius
 
    @celsius.setter
    def celsius(self, wert):
        if wert < -273.15:
            raise ValueError("Unter dem absoluten Nullpunkt")
        self._celsius = wert
 
    @property
    def fahrenheit(self):               # nur lesbar, wird berechnet
        return self._celsius * 9 / 5 + 32
 
t = Temperatur(25)
print(t.celsius, t.fahrenheit)
t.celsius = 100
print(t.fahrenheit)
try:
    t.celsius = -300
except ValueError as e:
    print("Fehler:", e)

Ausgabe:

25 77.0
212.0
Fehler: Unter dem absoluten Nullpunkt

slots

Mit __slots__ legst du fest, welche Attribute ein Objekt haben darf. Das spart Speicher und verhindert Tippfehler bei Attributnamen:

class Punkt:
    __slots__ = ("x", "y")
    def __init__(self, x, y):
        self.x, self.y = x, y
 
p = Punkt(1, 2)
try:
    p.z = 3
except AttributeError:
    print("kein Attribut z erlaubt")

Ausgabe:

kein Attribut z erlaubt

Merke

  • @dataclass erzeugt __init__, __repr__, __eq__ automatisch
  • frozen=True macht unveränderlich, order=True sortierbar
  • Veränderliche Standardwerte mit field(default_factory=...)
  • @property macht aus einer Methode ein Attribut, @x.setter prüft Zuweisungen
  • __slots__ beschränkt Attribute und spart Speicher

Übungsaufgabe

Schreibe eine Dataclass Buch mit Titel, Autor und Seitenzahl. Ergänze eine Property dick, die True liefert, wenn das Buch mehr als 500 Seiten hat.

Quiz zur Selbstkontrolle

Weiter im Kurs

Zurück: Spezielle Methoden (Dunder)

Weiter: Typ-Hints

Alle Kapitel: Python im Überblick