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