Python3-Metaklassen-Memo

Python3-Metaklassen-Memo

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.

Was ist eine Metaklasse?

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'>

Beispiel für die Verwendung einer Metaklasse (Singleton)

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.

Referenz

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

Python3-Metaklassen-Memo
Python-Memo
Python-Memo
Python-Memo
Python-Memo
Python-Memo
Python-Anfänger-Memo (9.2-10)
★ Memo ★ Python Iroha
[Python] EDA-Memo
Python 3-Operator-Memo
[Mein Memo] Python
[Python] Grundkarten-Memo
Python-Anfänger-Memo (2)
[Python] Numpy Memo
Python-Modul (Python-Lernnotiz ④)
Visualisierungsnotiz von Python
Python-Testpaket-Memo
[Python] Memo über Funktionen
Python-Memo für reguläre Ausdrücke
Memo zur Bisektionssuche (python2.7)
[Mein Memo] Python -v / Python -V
Python3-Memo vom Typ Liste / Wörterbuch
[Memo] Python 3-Listensortierung
Python-Tipps (mein Memo)
[Python] Memo Über Fehler
DynamoDB Script Memo (Python)
Python-Grundnotiz - Teil 2
Python-Rezeptbuch Memo
Grundlegende Python-Befehlsnotizen
Python OpenCV Tutorial Memo
Python grundlegende Grammatik Memo
TensorFlow API-Memo (Python)
Python nützliche Memo-Links
Python-Dekorator-Operationsnotiz
Python-Grundnotiz - Teil 1
Effektives Python-Memo Punkt 3
Ungefähre Aufzählung Python-Memo
Python-Memo (für mich): Array
Behandlung von Python-Ausnahmen (Python-Lernnotiz ⑥)
Memo zur Messung der Python-Ausführungszeit
Python
Twitter-Grafiknotiz mit Python
[Line / Python] Beacon-Implementierungsnotiz
Python und Ruby Slice Memo
Persönliches Python-Code-Memo
Raspeye + Python + OpenGL-Memo
Python-Grundgrammatik (Verschiedenes) Memo (3)
Unveränderlicher Python-Typ int memo
Python-Memo mit Perl --join
Python-Metaklasse und SQLalchemie deklarativ
Python-Grundgrammatik (Verschiedenes) Memo (2)
[MEMO] [Entwicklung der Entwicklungsumgebung] Python
Memo zur Erstellungsprozedur von [Python] virtualenv
Python-Grundgrammatik (Verschiedenes) Memo (4)
In Bezug auf die Beschleunigung von Python (Hinweis)
Python-Umgebungskonstruktionsnotiz unter Windows 10
Unterschied zwischen Java und Python (Memo)
[Python] Operationsnotiz von Pandas DataFrame