In den meisten bekannten OO-Sprachen ist ein Ausdruck wie SomeClass(arg1, arg2)
weist eine neue Instanz zu, initialisiert die Attribute der Instanz und gibt sie dann zurück.
In den meisten bekannten OO-Sprachen kann der Teil "Initialisierung der Attribute der Instanz" für jede Klasse angepasst werden, indem ein Konstrukteur der im Grunde nur ein Codeblock ist, der auf die neue Instanz einwirkt (unter Verwendung der dem Konstruktorausdruck übergebenen Argumente), um die gewünschten Anfangsbedingungen festzulegen. In Python entspricht dies der Klasse __init__
método.
Pythons __new__
ist nicht mehr und nicht weniger als eine ähnliche Anpassung des Teils "Zuweisung einer neuen Instanz" pro Klasse. Dies ermöglicht natürlich auch ungewöhnliche Dinge, wie z. B. die Rückgabe einer vorhandenen Instanz statt der Zuweisung einer neuen Instanz. In Python sollten wir diesen Teil also nicht unbedingt als Allokation betrachten; alles, was wir benötigen, ist, dass __new__
von irgendwoher ein passendes Beispiel findet.
Aber es ist immer noch nur die Hälfte des Jobs, und es gibt keine Möglichkeit für das Python-System zu wissen, dass Sie manchmal die andere Hälfte des Jobs ausführen wollen ( __init__
) und manchmal auch nicht. Wenn Sie dieses Verhalten wünschen, müssen Sie dies ausdrücklich sagen.
Oft kann man durch Refactoring erreichen, dass man nur noch __new__
oder so brauchen Sie nicht __new__
oder so, dass __init__
verhält sich bei einem bereits initialisierten Objekt anders. Aber wenn Sie es wirklich wollen, erlaubt Python es Ihnen, "den Job" neu zu definieren, so dass SomeClass(arg1, arg2)
ruft nicht unbedingt __new__
gefolgt von __init__
. Zu diesem Zweck müssen Sie eine Metaklasse erstellen und ihre __call__
método.
Eine Metaklasse ist einfach die Klasse einer Klasse. Und eine Klasse __call__
Methode steuert, was passiert, wenn Sie Instanzen der Klasse aufrufen. Also eine Metaklasse ' __call__
Methode steuert, was passiert, wenn Sie eine Klasse aufrufen, d.h. sie ermöglicht es Ihnen den Mechanismus der Instanzerstellung von Anfang bis Ende neu zu definieren . Dies ist die Ebene, auf der Sie am elegantesten einen völlig untypischen Instanzerstellungsprozess wie das Singleton-Muster implementieren können. Tatsächlich können Sie mit weniger als 10 Zeilen Code eine Singleton
Metaklasse, die es dann nicht einmal erforderlich macht, dass Sie sich mit __new__
überhaupt und können sich tout normale Klasse in ein Singleton verwandeln, indem Sie einfach __metaclass__ = Singleton
¡!
class Singleton(type):
def __init__(self, *args, **kwargs):
super(Singleton, self).__init__(*args, **kwargs)
self.__instance = None
def __call__(self, *args, **kwargs):
if self.__instance is None:
self.__instance = super(Singleton, self).__call__(*args, **kwargs)
return self.__instance
Dies ist jedoch wahrscheinlich eine tiefere Magie, als sie in dieser Situation wirklich gerechtfertigt ist!
1 Stimmen
Versuchte, Design Patterns zu verstehen, und hörte zum ersten Mal von :flyweight Design Patterns.. und sehr guter Link mit Beispielen in fast allen gängigen Sprachen.
5 Stimmen
Ist es nicht ein Singleton?