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

如何为Python对象unpacking添加type hints使Mypy正确推导类型?

问题:为Python对象解包实现类型提示,让Mypy正确推断类型

问题代码与现象

现有代码尝试为自定义类实现解包的类型提示,但直接解包对象时Mypy无法推断变量类型:

from typing import Tuple


class A:
    def __init__(self, x: int, y: str):
        self.x = x
        self.y = y

    def astuple(self) -> Tuple[int, str]:
        return self.x, self.y

    # 需要为__iter__标注返回类型
    def __iter__(self):
        return iter(self.astuple())


a = A(1, "a")
# 无法推断x和y的类型
x, y = a
reveal_type(x)
reveal_type(y)
# 能正确推断p和q的类型为int和str
p, q = a.astuple()
reveal_type(p)
reveal_type(q)

运行mypy后的输出:

$ mypy unpack_object.py
unpack_object.py:20: note: Revealed type is "Any"
unpack_object.py:21: note: Revealed type is "Any"
unpack_object.py:24: note: Revealed type is "builtins.int"
unpack_object.py:25: note: Revealed type is "builtins.str"
Success: no issues found in 1 source file

直接解包对象得到的x、y被推断为Any,但解包astuple()返回的元组时,p、q的类型能被正确识别。

解决方案

要让Mypy正确推断对象解包后的类型,需让类满足类型检查器的序列识别规则,推荐以下两种方案:

方案一:实现Sequence协议

通过定义__len__和__getitem__方法,让Mypy将类视为固定长度的序列,从而精准推断解包后每个变量的类型:

from typing import Tuple, Sequence, Iterator


class A(Sequence[int | str]):
    def __init__(self, x: int, y: str):
        self.x = x
        self.y = y

    def astuple(self) -> Tuple[int, str]:
        return self.x, self.y

    def __iter__(self) -> Iterator[int | str]:
        return iter(self.astuple())
    
    def __len__(self) -> int:
        return 2
    
    def __getitem__(self, index: int) -> int | str:
        if index == 0:
            return self.x
        elif index == 1:
            return self.y
        raise IndexError("Index out of range")


a = A(1, "a")
x, y = a
reveal_type(x)  # 推断为int
reveal_type(y)  # 推断为str
p, q = a.astuple()
reveal_type(p)
reveal_type(q)

方案二:精确标注__iter__并结合类型断言

若不想实现Sequence协议,可给__iter__标注返回迭代器的元素类型,再通过类型断言指定解包变量的精确类型:

from typing import Tuple, Iterator, Union


class A:
    def __init__(self, x: int, y: str):
        self.x = x
        self.y = y

    def astuple(self) -> Tuple[int, str]:
        return self.x, self.y

    def __iter__(self) -> Iterator[Union[int, str]]:
        return iter(self.astuple())


a = A(1, "a")
# 直接解包会得到Union[int, str]类型
x, y = a
reveal_type(x)  # 推断为Union[int, str]
reveal_type(y)  # 推断为Union[int, str]

# 手动指定精确类型
x: int = a[0]
y: str = a[1]

验证结果

使用方案一运行mypy后,输出如下:

$ mypy unpack_object.py
unpack_object.py:25: note: Revealed type is "builtins.int"
unpack_object.py:26: note: Revealed type is "builtins.str"
unpack_object.py:28: note: Revealed type is "builtins.int"
unpack_object.py:29: note: Revealed type is "builtins.str"
Success: no issues found in 1 source file

内容的提问来源于stack exchange,提问作者Aravind Nujella

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 19:10:20