import types
from functools import update_wrapper
from inspect import signature, Parameter
class MultiMethod:
def __init__(self, func):
update_wrapper(self, func)
self._method_dict = {}
self.add_method(func)
def add_method(self, func):
sig = signature(func)
# 此处 self 不需要 注解
param_types = tuple(param.annotation for param in sig.parameters.values() if param.name != 'self')
if Parameter.empty in param_types:
raise TypeError("annotation required for all params")
if param_types in self._method_dict:
raise TypeError("duplicate method signature")
self._method_dict[param_types] = func
return self
def __call__(self, *args):
# args 第一个参数是 foo实例,用来手动传入,绑定func的 self
# 后面的才是实际的参数
param_types = tuple(type(arg) for arg in args[1:])
if param_types in self._method_dict:
return self._method_dict[param_types](*args)
else:
raise TypeError("not method found")
def __get__(self, instance, owner):
if instance is None:
return self
else:
# foo.bar 时 手动绑定,返回一个绑定方法对象
return types.MethodType(self, instance)
class Foo:
@MultiMethod
def bar(self, a: int):
print(a)
@bar.add_method
def bar(self, a: int, b: int):
print(a, b)
if __name__ == "__main__":
f = Foo()
print(f.bar)
f.bar(1)
f.bar(1, 2)
f.bar('1')
Python 用装饰器类实现方法重载
于 2023-05-26 15:29:28 首次发布