设计思路
在新建类实例时,为子类方法添加装饰。因此任务拆解为对子类实例创建的检测与装饰的添加。
def mustcall(func):
if not hasattr(mustcall, "classname2fun"):
setattr(mustcall, "classname2fun", dict()) # Parent.func -> <Parent.func object at ...>
setattr(mustcall, "classnames", list()) # 注册的类名
classname2fun = getattr(mustcall, "classname2fun")
classnames = getattr(mustcall, "classnames")
classnames.append(func.__qualname__.split('.')[0])
classname2fun[func.__qualname__] = func # Parent.func -> <Parent.func object at ...>
return func
class MustCall:
def __new__(cls):
if cls.__name__ != __class__.__name__: # 检测到 MustCall的子类
if cls.__name__ not in getattr(mustcall, "classnames"): # 检测到 集成MustCAll基类的类的子类
# 获取父类的名称,即父类的父类含有MustCall
baseclassname = None
for base in cls.__bases__:
if any(base_.__name__ == __class__.__name__ for base_ in base.__bases__):
baseclassname = base.__name__
# 对子类进行方法封装
for classname, func in getattr(mustcall, "classname2fun").items():
if classname.split(".")[0] == baseclassname:
subfunc = getattr(cls, func.__name__)
def newfunc(self, *args, **kw):
func(self, *args, **kw)
subfunc(self, *args, **kw)
setattr(cls, func.__name__, newfunc)
return super().__new__(cls)
用法:
class Parent(MustCall):
@mustcall
def f(self):
print("parent call f")
class Child(Parent):
def f(self):
print(f"child's f says:")
p: Parent = Parent()
p.f()
p: Parent = Child()
p.f()