在Python静态类型检查工具Mypy中,函数类型重载允许我们为同一个函数定义多种不同的类型签名,从而适配不同的调用场景,让类型检查更精准。不同参数数量、不同参数类型的调用场景,都可以通过重载来明确对应的返回类型。

类型重载的基本前提
要实现函数类型重载,首先需要导入typing模块中的overload装饰器,重载的定义需要放在函数实际实现之前,且所有重载签名都不需要函数体,仅标注参数和返回类型即可。实际的函数实现需要兼容所有重载签名的逻辑,否则Mypy会提示类型错误。
单参数函数的类型重载
单参数函数的重载通常根据参数的不同类型,返回不同的结果类型。比如我们定义一个process_data函数,当传入字符串时返回字符串长度,传入整数时返回整数的平方:
from typing import overload
@overload
def process_data(data: str) -> int: ...
@overload
def process_data(data: int) -> int: ...
def process_data(data: str | int) -> int:
if isinstance(data, str):
return len(data)
else:
return data * data
# 调用测试
str_result: int = process_data("hello") # 类型正确,返回5
int_result: int = process_data(3) # 类型正确,返回9
上面的代码中,两个@overload装饰的签名分别对应字符串参数和整数参数的场景,实际实现中通过类型判断处理不同逻辑,Mypy会根据传入的参数类型匹配对应的重载签名,校验返回类型是否符合预期。
多参数函数的类型重载
多参数函数的重载可以结合参数数量、参数类型的组合来定义不同的签名。比如我们定义一个format_info函数,支持两种调用方式:传入姓名返回问候语,或者传入姓名和年龄返回带年龄的问候语:
from typing import overload
@overload
def format_info(name: str) -> str: ...
@overload
def format_info(name: str, age: int) -> str: ...
def format_info(name: str, age: int | None = None) -> str:
if age is None:
return f"Hello, {name}"
else:
return f"Hello, {name}, you are {age} years old"
# 调用测试
res1: str = format_info("Alice") # 匹配第一个重载,返回Hello, Alice
res2: str = format_info("Bob", 20) # 匹配第二个重载,返回Hello, Bob, you are 20 years old
如果多参数重载涉及不同类型的参数组合,也可以进一步扩展签名。比如下面的函数支持传入两个整数返回和,或者传入两个字符串返回拼接结果:
from typing import overload
@overload
def combine(a: int, b: int) -> int: ...
@overload
def combine(a: str, b: str) -> str: ...
def combine(a: int | str, b: int | str) -> int | str:
if isinstance(a, int) and isinstance(b, int):
return a + b
elif isinstance(a, str) and isinstance(b, str):
return a + b
else:
raise TypeError("参数类型不匹配")
# 调用测试
sum_result: int = combine(1, 2) # 返回3,类型正确
str_result: str = combine("a", "b") # 返回ab,类型正确
重载实现的注意事项
- 重载签名必须放在函数实际实现之前,且所有重载签名都没有函数体,以
...代替。 - 实际函数实现的参数类型需要覆盖所有重载签名的参数类型,返回类型也需要兼容所有重载的返回类型。
- 重载签名的顺序不影响Mypy的匹配逻辑,Mypy会优先匹配更具体的签名。
- 不要定义互相矛盾的重载签名,比如同一个参数类型对应两个不同的返回类型,会导致Mypy类型检查报错。
通过合理的类型重载定义,我们可以让Mypy更精准地识别函数不同调用场景下的类型,减少类型错误的发生,同时让代码的类型标注更清晰,方便其他开发者理解函数的使用方式。