When designing a subclass that inherits a certain class in Python, there are times when you want the inherited destination to do this kind of processing.
For example, you want to always call super () .__ init __ () when __init __
is called ...
Not limited to __init__
, the process of" I want to override the method of the parent class, but I want to call the method of the parent class as it is! "Often appears, but I forgot to write the process to call the method of the parent class. I don't want to throw an error, and the specification itself that calls the method of the parent class is troublesome in the first place.
This time, when the method f
of the child class is called, we will implement an implementation in which the method f
of the parent class is always called after the processing.
** Rewrite "child class function f" to "function new_f that executes child class function f and parent class function f" ** Write a metaclass that will do that
What is a metaclass? The story will be different this time. For the time being, think of it as a class that modifies the way classes are defined.
I believe that even people who are not familiar with it can do anything by copying and pasting the code below and rewriting the decorate
method.
Python: 3.7.2 (Maybe OK for Python3, only the metaclass specification method is different for Python2)
class ParentCaller(type):
def __new__(cls, name, base, attr):
#Prevent f in Parent class from calling f in Parent class
if name != "Parent":
#Make the function f automatically decorated when the class is created
attr["f"] = cls.decorate(attr["f"])
return super().__new__(cls, name, base, attr)
@classmethod
def decorate(cls, f):
#When the function f is received, f and Parent.Run f as a set new_Returns 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!
When writing a library like Tensorflow that people inherit and use, I want to avoid the promise of "Run hogehoge here!" As much as possible. In such a case, write a metaclass and call hogehoge without your knowledge.
It seems that metaprogramming is difficult to read and hated in group development. I think that it is an essence that minimizes man-hours for personal development.
Recommended Posts