Python OOP: Statische Member und Type-Annotation
https://oer-informatik.de/python_oop_static
https://bildung.social/@oerinformatik
tl/dr; (ca. 10 min Lesezeit): Neben Methoden und Instanzvariablen (Attributen), die das Verhalten und den Zustand einzelner Objekte speichern und verändern gibt es in der objektorientierten Programmierung auch Verhalten und Zustand, der einen gemeinsamen Zustand aller Objekte einer Klasse betrifft. Solche Klassenmethoden und Klassenvariablen werden in der OOP statisch genannt. Dieser Artikel beschreibt, wie sie in Python implementiert werden. (Zuletzt geändert am 02.03.2024)
Neben dem Objektzustand und dem Objektverhalten kann es auch Zustände und Verhalten geben, das an die Klasse gebunden ist - also nicht abhängt von Instanzvariablen.
Man speichert den Zustand einer Klasse, der nicht von einer Instanz abhängt, in statischen Variablen (manchmal spricht man auch von Klassenvariablen). Methoden, die keinen Objektzustand nutzen heißen entsprechend statische Methoden oder Klassenmethoden.
Ein einfaches Beispiel wäre eine Liste, die alle Instanzen einer Klasse speichert und Methoden, die diese Liste managen.
Statische Attribute / Klassenvariablen
Sofern das Attribut konten von allen Instanzen der Klasse Konto gleichermaßen genutzt werden soll, spricht man von einem statischen Attribut. In diesem Beispiel stellt konten eine Liste dar, in der alle Instanzen der Klasse gesammelt werden.
In Python wird ein statisches Attribut immer über den Klassennamen angesprochen (hier: Konten.konten). L
Statische Methoden / Klassenmethoden
Methoden einer Klasse, die keine Werte der Instanzen nutzen, werden statische Methoden genannt. Sinnvollerweise werden Sie nur dann an die Klassen gebunden, wenn Sie den Klassenzustand nutzen oder ihr Anwendungsfall eng mit der Klasse verbunden ist.
Im obigen Beispiel wurde eine Liste erzeugt, die alle Instanzen der Klassen hält. Die statische Methode konten_uebersicht() gibt einen Überblick über die einzelnen Instanzen. Im Gegensatz zu Methoden, die an Objektinstanzen gekoppelt sind, wird hier nicht die Referenz self als erstes Attribut erwartet:
class Konto:
konten = []
def __init__(self, ) -> None:
Konto.konten.append(self)
def konten_uebersicht() -> str:
kontouebersicht = ""
for konto in Konto.konten:
kontouebersicht += str(konto)+"\n"
return kontouebersichtIm UML-Klassendiagramm werden die statischen Methoden und Attribute unterstrichen:

Eine komplette Beispielklasse mit statischen Membern könnte als UML-Klassendiagramm etwa so aussehen:

Exkurs: Type-Annotations für eigene Klassen
Zur guten Dokumentation von Python-Code gehört auch, dass dieser mit Datentypen annotiert wird, wo eine solche Information zum Verständnis des Codes hilfreich ist. Bei Type-Annotations handelt es sich nicht um funktionalen Code, der ausgeführt wird oder eine typsicherheit generiert. Vielmehr handelt es sich um eine Art Kommentar, die zwar von Lintern oder Testumgebungen (pytest, pep8) ausgewertet werden kann.
Für Objektsammlungen (z.B. List) oder eigene Klassen sind hier Imports nötig (aus typing, für eigene Klassen z.B. ClassVar), damit die Type-Annotations korrekt erkannt werden.
Bei Klassen wird das beispielsweise so umgesetzt:
from typing import List, ClassVar
class Konto:
konto_stand: float
inhaber_name: str
konten: ClassVar[List['Konto']] = []
def __init__(self, inhaber_name: str, zinssatz: float) -> None:
self.konto_stand = 0
self.inhaber_name = inhaber_name
Konto.konten.append(self)Im Einzelnen:
Klassenvariablen werden mit “ClassVar” annotiert.
Die Typeannotation von Attributen erfolgt ohne vorangestelltes
selfan der Stelle, an der Klassenvariablen genannt werden.Die eigene neue Klasse kann nicht mit dem Typen selbst annotiert werden (
meinKonto: Konto), weil der zu diesem Zeitpunkt noch nicht verfügbar ist. Stattdessen wird einfach die Zeichenkette des Klassennamens zur Annotation genutzt.
Listing
Der Beispielcode ergibt sich mit den im obigen UML-Klassendiagramm modellierten Membern und Type-Annotations zu:
from typing import List, ClassVar
from datetime import datetime
class Konto:
konto_stand: float
inhaber_name: str
zinssatz: float
kontoauszug: List[str]
kontoauszug_nr: int
iban: str
konten: ClassVar[List['Konto']] = []
def __init__(self, inhaber_name: str, zinssatz: float) -> None:
self.konto_stand = 0
self.inhaber_name = inhaber_name
self.zinssatz = zinssatz
self.kontoauszug_nr = 0
self.kontoauszug = []
self.kontoauszug.append(self.kontoauszug_zeile("Kontoeröffnung von " + self.inhaber_name, 0))
self.iban = ""
Konto.konten.append(self)
def einzahlen(self, betrag: float) -> None:
self.konto_stand += betrag
self.kontoauszug_zeile("Einzahlung", betrag)
def auszahlen(self, betrag: float) -> None:
self.konto_stand -= betrag
self.kontoauszug_zeile("Auszahlung", betrag)
def kontoauszug_zeile(self, betreff:str, betrag:float) -> str:
zeit = datetime.now()
zeit = zeit.strftime("%d/%m/%Y %H:%M:%S")
self.kontoauszug_nr = self.kontoauszug_nr + 1
return zeit + " KtStand: %8.2f " % self.konto_stand + " Konto von " + self.inhaber_name + ", Auszug " + str(self.kontoauszug_nr) + ", Betrag: " + str(self.konto_stand)
def verzinsen(self) -> None:
self.konto_stand += self.konto_stand * self.zinssatz
def __str__(self) -> str:
return "Konto "+str(self.iban)+ " von "+self.inhaber_name+" Kontostand: "+str(self.konto_stand)
def konten_uebersicht() -> str:
kontouebersicht = ""
for konto in Konto.konten:
kontouebersicht += str(konto)+"\n"
return kontouebersicht
mein_konto = Konto("Dagobert Duck", 1.5)
sein_konto = Konto("Richie Rich", 3)
print(Konto.konten_uebersicht())Welche Member (Attribute, Methoden) bietet die Klasse object und wofür sind sie zuständig?
In Python erben alle Klassen von der Klasse object. Diese bietet eine Reihe von Methoden, die wir nutzen (und überschreiben) können.
Generell hilft uns dir(), um die Member einer Klasse ausgeben zu lassen (Pythonshell):
>> dir(object)
['__class__', '__delattr__', '__dir__', '__doc__',
'__eq__', '__format__', '__ge__', '__getattribute__',
'__gt__', '__hash__', '__init__', '__init_subclass__',
'__le__', '__lt__', '__ne__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__',
'__str__', '__subclasshook__']Infos zu den einzelnen Membern können wir aufrufen mit (Pythonshell):
Eine Kurzübersicht findet sich in folgendem UML-Klassen-Diagramm:

Weitere Literatur zu object
Hinweis zur Nachnutzung als Open Educational Resource (OER)
Dieser Artikel und seine Texte, Bilder, Grafiken, Code und sonstiger Inhalt sind - sofern nicht anders angegeben - lizenziert unter CC BY 4.0. Nennung gemäß TULLU-Regel bitte wie folgt: “Python OOP: Statische Member und Type-Annotation” von oer-informatik.de (H. Stein), Lizenz: CC BY 4.0. Der Artikel wurde unter https://oer-informatik.de/python_oop_static veröffentlicht, die Quelltexte sind in weiterverarbeitbarer Form verfügbar im Repository unter https://gitlab.com/oer-informatik/python-basics/erste-schritte-mit-python. Stand: 02.03.2024.
[Kommentare zum Artikel lesen, schreiben] / [Artikel teilen] / [gitlab-Issue zum Artikel schreiben]
