Python unterstützt drei Arten von Methoden in Klassendefinitionen: Instanzmethoden, Klassenmethoden und statische Methoden. Sie unterscheiden sich in der Art und Weise, wie sie aufgerufen werden und wie sie auf die Daten der Klasse und der Instanz zugreifen.
Hintergrund:
Ursprünglich waren Instanzmethoden (die mit "self") die einzige Art von Verhalten, wobei angenommen wurde, dass Methoden immer das Verhalten eines bestimmten Objekts aufrufen oder dessen Daten ändern/lesen. Später wurden in Python Klassenmethoden (mit "cls") eingeführt, die Verhalten für die gesamte Klasse bereitstellen (z.B. alternative Konstruktoren) und statische Methoden, die wie gewöhnliche Funktionen sind, aber mit der Klasse verbunden sind.
Problem:
Manchmal ist eine allgemeine Funktionalität für alle Instanzen erforderlich (statische Methoden). Manchmal muss eine Operation "für die gesamte Klasse" zugänglich sein (z.B. Erstellen einer Instanz). Wenn der Typ der Methode falsch definiert wird, können Bugs auftreten (z.B. versehentlich versuchen, die Klasse über eine Instanzmethode zu ändern oder umgekehrt).
Lösung:
Beispielcode:
class MyClass: def instance_method(self): return f"Instanz: {self}" @classmethod def class_method(cls): return f"Klasse: {cls}" @staticmethod def static_method(): return "Das ist eine statische Methode" obj = MyClass() print(obj.instance_method()) # Instanz: <MyClass object...> print(MyClass.class_method()) # Klasse: <class 'MyClass'> print(MyClass.static_method())# Das ist eine statische Methode
Schlüsselfunktionen:
Kann eine Instanzmethode direkt über die Klasse aufgerufen werden?
Ja, aber es muss explizit ein Objekt übergeben werden:
MyClass.instance_method(obj)
was selten sinnvoll ist.
Verhalten von statischen Methoden bei Vererbung: Können sie überschrieben werden?
Ja, man kann eine staticmethod in der abgeleiteten Klasse mit demselben Namen deklarieren, und genau diese wird aufgerufen, wenn aufgerufen wird.
Wozu werden Klassenmethoden verwendet, wenn man immer statische Methoden mit cls als Argument verwenden könnte?
cls ist nicht einfach nur ein erstes Argument: Bei classmethod setzt Python selbst die entsprechende Klasse als cls ein, selbst wenn der Aufruf aus einer abgeleiteten Klasse erfolgt. Dies ermöglicht die Erstellung einer alternativen Hierarchie von Konstruktoren ohne feste Bindung an den übergeordneten.
Beispiel:
class Base: @classmethod def make(cls): return cls() class Child(Base): pass Child.make() # gibt Child zurück, nicht Base
Im Projekt wurden gewöhnliche Methoden zur Erstellung alternativer Instanzen verwendet (z.B. create_from_json). Dadurch gab die Methode bei Vererbung immer das Objekt der Basisklasse und nicht das des Erben zurück.
Vorteile:
Nachteile:
Es wurden classmethod-Fabriken implementiert, die Instanzen der aktuellen Klasse (cls()) zurückgeben, selbst wenn sie aus einem Erben aufgerufen werden.
Vorteile:
Nachteile: