Lors de la conception d'une sous-classe qui hérite d'une certaine classe en Python, vous souhaitez parfois que la destination héritée effectue ce type de traitement.
Par exemple, je veux que vous appeliez super () .__ init __ () chaque fois que __init __
est appelé ...
Non limité à __init__
, le processus de" Je veux remplacer la méthode de la classe parente, mais je veux appeler la méthode de la classe parente telle quelle! "Apparaît souvent, mais j'ai oublié d'écrire le processus d'appel de la méthode de la classe parente. Je ne veux pas faire d'erreur, et la spécification elle-même qui appelle la méthode de la classe parent est gênante en premier lieu.
Cette fois, lorsque la méthode f
de la classe enfant sera appelée, nous essaierons d'implémenter une implémentation dans laquelle la méthode f
de la classe parent est toujours appelée après le traitement.
** Réécrire "fonction de classe enfant f" en "fonction new_f qui exécute la fonction de classe enfant f et la fonction de classe parent f" ** Ecrire une méta classe qui fait ça
Qu'est-ce qu'une méta-classe? L'histoire sera différente cette fois. Pour le moment, pensez-y comme une classe qui modifie la façon dont les classes sont définies.
Je crois que même les personnes qui ne le connaissent pas peuvent tout faire en copiant et collant le code ci-dessous et en réécrivant la méthode decorate
.
Python: 3.7.2 (Peut-être OK pour Python3, seule la méthode de spécification de la métaclasse est différente pour Python2)
class ParentCaller(type):
def __new__(cls, name, base, attr):
#Empêcher f dans la classe Parent d'appeler f dans la classe Parent
if name != "Parent":
#Rendre la fonction f automatiquement décorée lors de la création de la classe
attr["f"] = cls.decorate(attr["f"])
return super().__new__(cls, name, base, attr)
@classmethod
def decorate(cls, f):
#Lorsque la fonction f est reçue, f et Parent.Exécuter f comme un nouvel ensemble_Renvoie f
def new_f(self, x):
f(self, x)
Parent.f(self, x)
return new_f
class Parent(metaclass=ParentCaller):
def f(self, x):
print(f"parent's f says: {x}")
class Child(Parent):
def f(self, x):
print(f"child's f says: {x}")
child = Child()
child.f("Hello World!")
# child's f says: Hello World!
# parent's f says: Hello World!
Lorsque vous écrivez une bibliothèque comme Tensorflow dont les gens héritent et utilisent, je veux éviter autant que possible la promesse de "Run hogehoge here!". Dans un tel cas, écrivez une méta-classe et appelez hogehoge à votre insu.
Il semble que la méta-programmation soit difficile à lire et détestée dans le développement de groupe. Je pense que c'est une essence qui minimise le nombre d'étapes de développement personnel.
Recommended Posts