Python中的重载
方法重载是面向对象中一个非常重要的概念,在类中包含了成员方法和构造方法。如果类中存在多个同名,且参数(个数和类型)不同的成员方法或构造方法,那么这些成员方法或构造方法就被重载了
java案例
class MyOverload {
public MyOverload() {
System.out.println("MyOverload");
}
public MyOverload(int x) {
System.out.println("MyOverload_int:" + x);
}
public MyOverload(long x) {
System.out.println("MyOverload_long:" + x);
}
public MyOverload(String s, int x, float y, boolean flag) {
System.out.println("MyOverload_String_int_float_boolean:" + s + x + y + flag);
}
}
先说结论:python语法上不支持重载,但可通过魔法方法或装饰器实现重载的效果
Python版本>=3.8 : functools
新增了一个 singledispatchmethod
方法,这个方法可以让 Python 的类方法支持 重载
,使用方法和 singledispatch
类似,唯一需要注意的是,重载的类型是由类函数中第一个非 self
和 cls
的参数类型决定的,singledispatchmethod
还支持嵌套的装饰器,不过需要注意的是,dispatcher.register
和 singledispatchmethod
需要在绝大多数装饰器的最上层
官方实例:
class Negator:
@singledispatchmethod
def neg(self, arg):
raise NotImplementedError("Cannot negate a")
@neg.register
def _(self, arg: int):
return -arg
@neg.register
def _(self, arg: bool):
return not arg
Python版本<3.8 : 借鉴singledispatchmethod实现
3.8源码
class singledispatchmethod:
"""Single-dispatch generic method descriptor.
Supports wrapping existing descriptors and handles non-descriptor
callables as instance methods.
"""
def __init__(self, func):
if not callable(func) and not hasattr(func, "__get__"):
raise TypeError(f"{func!r} is not callable or a descriptor")
self.dispatcher = singledispatch(func)
self.func = func
def register(self, cls, method=None):
"""generic_method.register(cls, func) -> func
Registers a new implementation for the given *cls* on a *generic_method*.
"""
return self.dispatcher.register(cls, func=method)
def __get__(self, obj, cls=None):
def _method(*args, **kwargs):
method = self.dispatcher.dispatch(args[0].__class__)
return method.__get__(obj, cls)(*args, **kwargs)
_method.__isabstractmethod__ = self.__isabstractmethod__
_method.register = self.register
update_wrapper(_method, self.func)
return _method
@property
def __isabstractmethod__(self):
return getattr(self.func, '__isabstractmethod__', False)
################################################################################
### cached_property() - computed once per instance, cached as attribute
################################################################################
_NOT_FOUND = object()
具体实现:
需要重载处添加如下代码:
from functools import singledispatch, update_wrapper
def methdispatch(func):
dispatcher = singledispatch(func)
def wrapper(*args, **kw):
return dispatcher.dispatch(args[1].__class__)(*args, **kw)
wrapper.register = dispatcher.register
update_wrapper(wrapper, func)
return wrapper
测试代码:
class Negator:
@methdispatch
def neg(self, arg):
raise NotImplementedError("Cannot negate a")
@neg.register
def _(self, arg: int):
return -arg
@neg.register
def _(self, arg: bool):
return not arg
if __name__ == '__main__':
neg = Negator()
neg.neg(1)
neg.neg(False)
# 输出如下:
# -1
# True
其他
在 pypi 上也有对应的 singledispatchmethod · PyPI 库,可以通过 pip 安装后直接使用,用法和 3.8 之后版本用法一致。
参考内容:
本文来自博客园,作者:Mkdir-p,转载请注明原文链接:https://www.cnblogs.com/touchTomorrow/p/16455276.html