Ein Hinweis darauf, was Python-Anfänger über Python 3-Metaklassen gelernt haben Die Kommentare im Code sind für die Konsolenausgabe vorgesehen. Wir würden uns freuen, wenn Sie auf Fehler oder falsche Ausdrücke hinweisen könnten.
Mit type () können Sie herausfinden, welcher Klassentyp eine Instanz ist.
class Hoge:
pass
h = Hoge()
print(type(h))
# <class '__main__.Hoge'>
Versuchen Sie, type () auch auf die Hoge-Klasse anzuwenden.
print(type(Hoge))
# <class 'type'>
Dies zeigt an, dass die Hoge-Klasse selbst eine Instanz vom Typ Typ ist. So wie h eine Instanz der Hoge-Klasse ist, ist die Hoge-Klasse auch eine Instanz der Typklasse. *** Eine in Python3 definierte Klasse wird zu einer Instanz einer speziellen Klasse (Metaklasse) namens type. *** Wenn eine Klasse definiert ist, wird normalerweise der Typ (Klassenname, Oberklassen, Attribute_Dict) mit drei Argumenten aufgerufen und eine Instanz dieser Klasse erstellt. Es ist auch möglich, der Typklasse explizit drei Argumente zuzuweisen und anstelle der "normalen" Definitionsmethode eine Klasseninstanz zu erstellen. Die obige Hoge-Klasse kann mit type als ↓ definiert werden. (Übergeben Sie den Klassennamen im ersten Argument, die übergeordnete Klasse im zweiten Argument und das Namespace-Wörterbuch im dritten Argument.)
Hoge = type('Hoge', (), {})
h = Hoge()
print(type(h))
# <class '__main__.Hoge'>
Die Typklasse, die eine Klasseninstanz erstellt, ähnelt einer Factory, die eine Klasse erstellt (eine Instanz von) und als *** Metaklasse *** bezeichnet wird. Wenn der Interpreter vor der Deklaration der Hoge-Klasse steht, wird standardmäßig \ _ \ _ new \ _ \ _ der Typklasse aufgerufen und eine Klasseninstanz generiert. Die Metaklasse kann jedoch durch Erben dieser Typklasse angepasst werden. .. Im Folgenden finden Sie ein Beispiel für das Festlegen einer MetaTest-Klasse, die beim Deklarieren einer Klasse den Typ anstelle des Standardtyps erbt.
class MetaTest(type):
def __new__(cls, clsname, superclasses, attributedict):
print("Metaklassentest")
class HogeHoge(metaclass=MetaTest):
pass
#Metaklassentest
h = HogeHoge()
# TypeError: 'NoneType' object is not callable
MetaTest erbt von der Standardmetaklasse, der Typklasse, und überschreibt die \ _ \ _ new \ _ \ _ -Methode, mit der eine Klasseninstanz erstellt wird. Hier wird die Zeichenfolge nur ausgegeben, ohne eine Klasseninstanz zu erstellen. Wenn Sie eine HogeHoge-Klasse mit MetaTest als Metaklasse deklarieren, wird daher MetaTest. \ _ \ _ New \ _ \ _, das nur eine Zeichenfolge zurückgibt, anstelle des Typs verwendet. \ _ \ _ New \ _ \ _, der eine Klasseninstanz erstellt. Namens. Die Konsole zeigte auch "Test Metaclass" an. Beim nächsten Versuch, eine Instanz der HogeHoge-Klasse zu erstellen, wurde eine Fehlermeldung angezeigt. Die MetaTest-Klasse hat keine Instanz der HogeHoge-Klasse erstellt (wird ein None-Objekt erstellt?). Wenn Sie den übergeordneten Klassentyp \ _ \ _ new \ _ \ _ überschreiben, wird die Klasseninstanz nicht erstellt. Der Aufruf des Typs. \ _ \ _ New \ _ \ _ im Rückgabewert von \ _ \ _ new \ _ \ _ zum Zurückgeben einer Klasseninstanz oder zum Überschreiben von \ _ \ _ init \ _ \ _ funktioniert (\ _ \ _ new \ Klasseninstanz erstellt, als _ \ _ zuerst aufgerufen wurde?).
class MetaTestA(type):
def __new__(cls, clsname, superclasses, attributedict):
print("Metaklasse Ein Test")
return type.__new__(cls, clsname, superclasses, attributedict)
class MetaTestB(type):
def __init__(cls, clsname, superclasses, attributedict):
print("Metaclass B-Test")
class HogeHogeA(metaclass=MetaTestA):
pass
#Metaklasse Ein Test
class HogeHogeB(metaclass=MetaTestB):
pass
#Metaclass B-Test
a = HogeHogeA()
b = HogeHogeB()
print(type(a))
# <class '__main__.HogeHogeA'>
print(type(b))
# <class '__main__.HogeHogeB'>
Sie können das Verhalten von Klasseninstanzen steuern, indem Sie Metaklassen anpassen. Die hier Site, auf die ich mich diesmal bezog, führt ein Singleton-Muster wie ↓ ein, das Metaklassen verwendet.
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
class SingletonClass(metaclass=Singleton):
pass
class RegularClass():
pass
x = SingletonClass()
y = SingletonClass()
print(x == y)
# True
x = RegularClass()
y = RegularClass()
print(x == y)
# False
Eine Instanz mit einer \ _ \ _ call \ _ \ _ -Methode (sie scheint fähig zu sein) kann \ _ \ _ call \ _ \ _ wie eine Funktion mit dem Instanznamen () aufrufen. Singleton, eine Metaklasse, die den Typ erbt, überschreibt die Typklasse \ _ \ _ call \ _ \ _. \ _ \ _ Call \ _ \ _ wird jedes Mal aufgerufen, wenn eine SingletonClass-Klasse (eine Klasse, die eine Instanz von Singleton ist) mit Singleton als Metaklasse im Format SingletonClass () geschrieben wird (jedes Mal, wenn eine SingletonClass instanziiert wird). Getan werden. In \ _ \ _ call \ _ \ _ wird geprüft, ob die Instanz in \ _instances gespeichert ist, und wenn die Instanz nicht vorhanden ist, wird die Methode \ _ \ _ call \ _ \ _ vom Typ aufgerufen, die die übergeordnete Klasse von Singleton ist. , SingletonClass wird instanziiert (wobei \ _ \ _ call \ _ \ _ vom Typ SingletonClass zu instanziieren scheint, aber ich bin mir über die Details nicht sicher). Wenn in \ _instances bereits eine Instanz vorhanden ist, wird keine neue Instanz erstellt. Andererseits wird RegularClass, dessen Metaklasse die Standardtypklasse ist, jedes Mal instanziiert.
https://www.yunabe.jp/docs/python_metaclass.html https://www.python-course.eu/python3_metaclasses.php https://realpython.com/python-metaclasses/ https://teratail.com/questions/180387
Recommended Posts