You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何改写代码使mypy兼容numbers.Number处理数值类对象序列?

问题描述

我希望使用mypy的静态鸭子类型特性编写一个函数,处理由numbers.Number定义的“类数值对象”序列,代码示例如下:

from numbers import Number
from typing import Sequence

def something_numerical(xs: Sequence[Number]) -> Number:
    ...

print(something_numerical([1., 2., 3.]))

但调用该函数传入float或int列表时,mypy报错:

$ print(multiply([1., 2., 3.]))
foo/foo.py:9: error: List item 0 has incompatible type "float"; expected "Number"
foo/foo.py:9: error: List item 1 has incompatible type "float"; expected "Number"
foo/foo.py:9: error: List item 2 has incompatible type "float"; expected "Number"

已知float并非numbers.Number的子类,但numbers模块的抽象基类(ABC)用于检查对象是否具备数值操作所需方法。请问如何改写代码,既能处理int、float、fractions.Fraction等类型,又能通过mypy的类型检查?

解决方案

方法1:显式声明数值类型的Union

直接定义包含所有目标数值类型的Union,配合Sequence使用,让mypy明确识别允许的输入类型:

from numbers import Number
from typing import Sequence, Union
import fractions

# 列出所有需要支持的数值类型,包含Number以兼容自定义注册类型
NumericalType = Union[int, float, fractions.Fraction, Number]

def something_numerical(xs: Sequence[NumericalType]) -> NumericalType:
    total = xs[0]
    for num in xs[1:]:
        total += num
    return total

# 测试调用
print(something_numerical([1., 2., 3]))
print(something_numerical([fractions.Fraction(1,2), fractions.Fraction(3,4)]))

方法2:使用带边界的TypeVar实现泛型

通过绑定到Number的TypeVar创建泛型函数,既支持所有Number兼容类型,又能保证输入输出类型一致:

from numbers import Number
from typing import Sequence, TypeVar

# 定义绑定到Number的类型变量,限制输入必须是Number兼容类型
T = TypeVar('T', bound=Number)

def something_numerical(xs: Sequence[T]) -> T:
    total = xs[0]
    for num in xs[1:]:
        total += num
    return total

# 测试调用
print(something_numerical([1., 2., 3.]))
print(something_numerical([1, 2, 3]))

关键说明

numbers.Number是抽象基类,int、float等是它的虚拟子类(通过register方法注册,而非直接继承)。mypy默认不识别虚拟子类的类型兼容关系,因此需要通过上述方式明确类型约束,才能通过静态检查。两种方法中,泛型方式更灵活,适合需要支持自定义数值类型的场景;Union方式更直观,适合明确知道需要支持的具体类型的场景。

内容的提问来源于stack exchange,提问作者Alex Flint

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 23:33:30