如何通过类型检查确保Python函数遵循同一接口(使用mypy)
更Pythonic的方式让多个函数遵循同一类型接口(基于mypy)
方法1:直接为函数添加类型注解(最简洁)
不需要额外的中间变量,直接在函数定义时明确参数和返回值类型,mypy会自动验证签名是否匹配你定义的接口:
from typing import Callable # 定义接口类型 BinaryFunction = Callable[[float, float], float] # 直接给函数添加类型注解 def plus(a: float, b: float) -> float: return a + b def minus(a: float, b: float) -> float: return a - b
这种写法完全符合Python风格,没有冗余代码。当你需要将这些函数传递给标注了BinaryFunction类型的参数时,mypy会自动校验兼容性:
def calculate(op: BinaryFunction, x: float, y: float) -> float: return op(x, y) # mypy会正常通过校验 calculate(plus, 1.5, 2.5) calculate(minus, 3.0, 1.0)
方法2:使用Protocol定义接口(更灵活,适合复杂场景)
如果需要更接近"接口"的语义(比如未来可能扩展约束),可以用Python 3.8+的Protocol(3.8以下可通过typing_extensions导入),它比Callable更灵活,支持定义复杂调用签名或附加属性:
from typing import Protocol # 定义协议(接口) class BinaryFunction(Protocol): def __call__(self, a: float, b: float) -> float: ... # 实现函数无需显式继承,mypy会自动校验是否符合协议 def plus(a: float, b: float) -> float: return a + b def minus(a: float, b: float) -> float: return a - b # 使用接口类型 def apply_operation(op: BinaryFunction, x: float, y: float) -> float: return op(x, y)
这种方式语义更清晰,后续扩展接口(比如要求函数具备某个属性)时,只需修改BinaryFunction协议即可,无需改动所有函数定义。
为什么原写法不够Pythonic?
你之前用checkedPlus: BinaryFunction = plus的方式,是通过额外变量触发类型校验,但这个变量在运行时没有实际用途,属于冗余代码。上面两种方法遵循了Python"显式优于隐式"的原则,直接在函数定义或接口层面明确约束,代码更简洁易懂。
内容的提问来源于stack exchange,提问作者chichak
相关产品推荐
相关产品推荐

