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

为何直接迭代自定义Iterable对象类型正常,zip中却为Any?

问题:为何直接迭代与zip中迭代的类型推断结果不同?

测试脚本

from collections.abc import Iterable, Iterator


class A(Iterable):
    _list: list[int]

    def __init__(self, *args: int) -> None:
        self._list = list(args)

    def __iter__(self) -> Iterator[int]:
        return iter(self._list)


a = A(1, 2, 3)

for i in a:
    reveal_type(i)

for s, j in zip("abc", a):
    reveal_type(j)

mypy运行输出

$ mypy test.py
test.py:17: note: Revealed type is "builtins.int"
test.py:20: note: Revealed type is "Any"
Success: no issues found in 1 source file

问题

为何直接迭代对象a时类型为int,而在zip中迭代时j的类型却为Any?

注:子类化class A(Iterable[int])可实现正确类型解析,但这并非本次问题的关注点;)

原因解析

这是因为mypy在两种场景下的类型推断逻辑存在差异:

  • 直接迭代场景:当在for循环中直接迭代a时,mypy会直接解析__iter__方法的返回类型。由于你的__iter__明确标注返回Iterator[int],mypy可以直接确定迭代元素的类型是int。
  • zip调用场景:zip函数的类型推断依赖于传入参数的泛型类型声明。你的类A继承的是未指定类型参数的Iterable,这在类型检查中等价于Iterable[Any]。当zip处理a时,它会使用Iterable的默认泛型参数Any,而不会从__iter__方法的返回类型逆向推导父类的泛型参数——mypy的类型推断规则不会为了适配zip的调用,去动态补全父类的泛型信息。

简单来说,直接迭代时mypy关注的是__iter__的具体返回类型,而zip则依赖类声明时的泛型标注,两者的类型推断路径不同,导致了结果差异。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 17:52:08