我一直很好奇 Python 的 overload
是怎么个重载,和C++类似么,今天查了下才知道 😂
overload
是 Python typing
模块中的一个装饰器,用于标记函数的不同签名,以便为静态类型检查工具提供类型信息。它本身不实现任何逻辑,也不会在运行时影响函数的行为。相反,它用于帮助类型检查器理解函数的不同可能调用方式。
当你使用 @overload
时,你需要在定义的最后提供一个实际实现的函数。这个实现函数将处理所有的调用逻辑,而 @overload
标记的函数仅用于类型检查。
下面是一些使用 @overload
装饰器的例子:
1. 基础用法
考虑一个处理整数和字符串的函数,返回不同类型的结果。
from typing import overload, Union
@overload
def process(value: int) -> int: ...
@overload
def process(value: str) -> str: ...
def process(value: Union[int, str]) -> Union[int, str]:
if isinstance(value, int):
return value * 2
elif isinstance(value, str):
return value[::-1]
else:
raise ValueError("Unsupported type")
# 使用示例
print(process(3)) # 输出: 6
print(process("abc")) # 输出: "cba"
在这个例子中,process
函数可以接受整数或字符串,并根据输入类型返回不同的结果。@overload
只是为了让类型检查器知道可能的输入输出类型组合。
2. 例子:带有切片的用法
考虑一个支持整数索引和切片的自定义列表类:
from typing import overload, List, Union
class MyList:
def __init__(self, data: List[int]):
self.data = data
@overload
def __getitem__(self, index: int) -> int: ...
@overload
def __getitem__(self, index: slice) -> List[int]: ...
def __getitem__(self, index: Union[int, slice]) -> Union[int, List[int]]:
return self.data[index]
# 使用示例
my_list = MyList([1, 2, 3, 4, 5])
print(my_list[1]) # 输出: 2
print(my_list[1:3]) # 输出: [2, 3]
在这个例子中,MyList
类定义了一个 __getitem__
方法,可以接受整数或切片作为参数。@overload
用来告诉类型检查器不同的输入输出类型。
3. 例子:使用 __call__
方法
当一个类的实例被调用时,可以使用 __call__
方法定义其行为:
from typing import overload, List
class CallableObject:
@overload
def __call__(self, x: int) -> int: ...
@overload
def __call__(self, x: str) -> str: ...
def __call__(self, x: Union[int, str]) -> Union[int, str]:
if isinstance(x, int):
return x * 2
elif isinstance(x, str):
return x[::-1]
else:
raise ValueError("Unsupported type")
# 使用示例
callable_obj = CallableObject()
print(callable_obj(5)) # 输出: 10
print(callable_obj("hello")) # 输出: "olleh"
在这个例子中,CallableObject
类实现了 __call__
方法,可以接受整数或字符串,并根据输入类型返回不同的结果。
总结
@overload
本身不实现逻辑,实际的实现需要通过一个不带 @overload
的函数来完成。它主要用于为类型检查器提供多个函数签名的信息,帮助在静态类型检查中更好地理解代码。