Mémo de métaclasse Python3

Mémo de métaclasse Python3

Une note de ce que les débutants en Python ont appris sur les métaclasses Python 3 Les commentaires dans le code sont destinés à la sortie de la console. Nous vous serions reconnaissants de bien vouloir signaler toute erreur ou expression incorrecte.

Qu'est-ce qu'une métaclasse?

Vous pouvez utiliser type () pour découvrir le type de classe d'une instance.

class Hoge:
    pass
h = Hoge()
print(type(h))
# <class '__main__.Hoge'>

Essayez également d'appliquer type () à la classe Hoge.

print(type(Hoge))
# <class 'type'>

Cela indique que la classe Hoge elle-même est une instance de type type. Tout comme h est une instance de la classe Hoge, la classe Hoge est également une instance de la classe type. *** Une classe définie dans Python3 devient une instance d'une classe spéciale (métaclasse) appelée type. *** Normalement, lorsqu'une classe est définie, le type (nom de classe, superclasses, attribut_dict) avec trois arguments est appelé et une instance de cette classe est créée. Il est également possible de donner explicitement trois arguments à la classe de type et de créer une instance de classe au lieu de la méthode de définition "normale". La classe Hoge ci-dessus peut être définie comme ↓ en utilisant type. (Passez le nom de la classe dans le premier argument, la classe parent taple dans le deuxième argument et le dictionnaire d'espaces de noms dans le troisième argument)

Hoge = type('Hoge', (), {})
h = Hoge()
print(type(h))
# <class '__main__.Hoge'>

La classe de type qui crée une instance de classe est comme une fabrique qui crée (une instance de) une classe et s'appelle *** métaclasse ***. Lorsque l'interpréteur fait face à la déclaration de la classe Hoge, par défaut \ _ \ _ new \ _ \ _ de la classe de type est appelée et une instance de classe est créée, mais vous pouvez personnaliser la classe méta en héritant de cette classe de type. .. Voici un exemple de définition d'une classe MetaTest qui hérite du type au lieu du type par défaut lors de la déclaration d'une classe.

class MetaTest(type):
    def __new__(cls, clsname, superclasses, attributedict):
        print("Test de métaclasse")
class HogeHoge(metaclass=MetaTest):
    pass
#Test de métaclasse
h = HogeHoge()
# TypeError: 'NoneType' object is not callable

MetaTest hérite de la métaclasse par défaut, la classe de type, et remplace la méthode \ _ \ _ new \ _ \ _ qui crée une instance de classe. Ici, la chaîne de caractères est simplement sortie sans créer d'instance de classe. Par conséquent, lors de la déclaration d'une classe HogeHoge avec MetaTest défini comme métaclasse, MetaTest. \ _ \ _ New \ _ \ _ qui ne renvoie qu'une chaîne de caractères est utilisé à la place du type. \ _ \ _ New \ _ \ _ qui crée une instance de classe. Appelé. La console affiche également "Test Metaclass". La prochaine fois que j'ai essayé de créer une instance de la classe HogeHoge, j'ai eu une erreur. La classe MetaTest n'a pas créé d'instance de la classe HogeHoge (un objet None a-t-il été créé?). Si vous remplacez le type de classe parent \ _ \ _ nouveau \ _ \ _, l'instance de classe ne sera pas créée. Type d'appel. \ _ \ _ New \ _ \ _ dans la valeur de retour de \ _ \ _ new \ _ \ _ pour renvoyer une instance de classe ou remplacer \ _ \ _ init \ _ \ _ fonctionnera (\ _ \ _ nouveau ) Instance de classe créée lorsque _ \ _ a été appelé en premier?).

class MetaTestA(type):
    def __new__(cls, clsname, superclasses, attributedict):
        print("Test de la métaclasse A")
        return type.__new__(cls, clsname, superclasses, attributedict)
class MetaTestB(type):
    def __init__(cls, clsname, superclasses, attributedict):
        print("Test de la métaclasse B")
class HogeHogeA(metaclass=MetaTestA):
    pass
#Test de la métaclasse A
class HogeHogeB(metaclass=MetaTestB):
    pass
#Test de la métaclasse B
a = HogeHogeA()
b = HogeHogeB()
print(type(a))
# <class '__main__.HogeHogeA'>
print(type(b))
#  <class '__main__.HogeHogeB'>

Exemple d'utilisation de la méta classe (Singleton)

Vous pouvez contrôler le comportement des instances de classe en personnalisant les métaclasses. Le site here auquel j'ai fait référence cette fois présente un modèle Singleton comme ↓ qui utilise des métaclasses.

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

Une instance avec une méthode \ _ \ _ call \ _ \ _ (elle semble appelée able) peut appeler \ _ \ _ call \ _ \ _ comme une fonction avec le nom d'instance (). Singleton, une métaclasse qui hérite du type, remplace la classe de type \ _ \ _ call \ _ \ _. \ _ \ _ Call \ _ \ _ est appelé chaque fois qu'une classe SingletonClass (une classe qui est une instance de Singleton) avec Singleton défini comme métaclasse est écrite au format SingletonClass () (chaque fois qu'une SingletonClass est instanciée). Sera fait. A l'intérieur de \ _ \ _ call \ _ \ _, il vérifie si l'instance est stockée dans \ _instances, et si l'instance n'existe pas, la méthode \ _ \ _ call \ _ \ _ de type, qui est la classe parente de Singleton, est appelée. , SingletonClass est instancié (où \ _ \ _ call \ _ \ _ de type semble instancier SingletonClass, mais je ne suis pas sûr des détails). Si une instance existe déjà dans \ _instances, aucune nouvelle instance ne sera créée. D'autre part, RegularClass, dont la métaclasse est la classe de type par défaut, est instanciée à chaque fois.

référence

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

Mémo de métaclasse Python3
Mémo Python
mémo python
mémo python
Mémo Python
Mémo Python
[Python] Mémo sur le dictionnaire
mémo débutant python (9.2-10)
★ Mémo ★ Python Iroha
[Python] Mémo EDA
Mémo opérateur Python 3
[Mon mémo] python
[Python] Mémo de fond de carte
Mémo débutant Python (2)
[Python] Mémo Numpy
Module Python (mémo d'apprentissage Python ④)
Mémo de visualisation par Python
Mémo du package de test Python
[Python] Mémo sur les fonctions
mémo d'expression régulière python
Recherche de bisection (python2.7) mémo
[Mon mémo] python -v / python -V
Mémo de type Liste / Dictionnaire Python3
[Mémo] Tri de liste Python3
Astuces Python (mon mémo)
[Python] Mémo sur les erreurs
Mémo de script DynamoDB (Python)
Mémo de base Python - Partie 2
livre de recettes python Memo
Notes de commande de base Python
Mémo du didacticiel Python OpenCV
Mémo de grammaire de base Python
Mémo de l'API TensorFlow (Python)
liens de mémo utiles python
Mémo d'opération de décorateur Python
Mémo de base Python - Partie 1
Élément de mémo Python efficace 3
Mémo Python d'énumération approximative
Mémo Python (pour moi): Array
Gestion des exceptions Python (mémo d'apprentissage Python ⑥)
Mémo de mesure du temps d'exécution Python
Python
Mémo graphique Twitter avec Python
[Line / Python] Mémo d'implémentation Beacon
Mémo tranche python et rubis
Mémo de code personnel Python
Raspeye + Python + Mémo OpenGL
Grammaire de base Python (divers) Mémo (3)
Mémo int de type immuable Python
mémo python utilisant perl --join
métaclasse python et déclaration sqlalchemy
Grammaire de base Python (divers) Mémo (2)
[MEMO] [Construction de l'environnement de développement] Python
[Python] mémo de procédure de création virtualenv
Grammaire de base Python (divers) Mémo (4)
Concernant l'accélération de python (Note)
Mémo de construction de l'environnement Python sur Windows 10
Différence entre java et python (mémo)
[Python] Mémo d'opération de pandas DataFrame