跳到内容

iter-method-return-iterable (PYI045)

源自 flake8-pyi 代码检查器。

作用

检查存根 (stub) 中 __iter__ 方法的返回值是否为 Iterable[T] 而不是 Iterator[T]

为什么这不好?

__iter__ 方法应该始终返回某种类型的 Iterator,而不是 Iterable

在 Python 中,Iterable 是具有 __iter__ 方法的对象;Iterator 是具有 __iter____next__ 方法的对象。所有 __iter__ 方法都应返回 Iterator。如果对象的 __iter__ 方法没有返回 Iterator,类型检查器可能无法始终识别该对象为可迭代对象。

每个 Iterator 都是 Iterable,但并非每个 Iterable 都是 Iterator。例如,listIterable,但不是 Iterator;您可以通过将列表传递给 iter() 来获得列表元素的迭代器。

>>> import collections.abc
>>> x = [42]
>>> isinstance(x, collections.abc.Iterable)
True
>>> isinstance(x, collections.abc.Iterator)
False
>>> next(x)
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: 'list' object is not an iterator
>>> y = iter(x)
>>> isinstance(y, collections.abc.Iterable)
True
>>> isinstance(y, collections.abc.Iterator)
True
>>> next(y)
42

使用 Iterable 而不是 Iterator 作为 __iter__ 方法的返回类型意味着您不一定能够对返回的对象调用 next(),这违反了接口的预期。

示例

import collections.abc


class Klass:
    def __iter__(self) -> collections.abc.Iterable[str]: ...

建议改为

import collections.abc


class Klass:
    def __iter__(self) -> collections.abc.Iterator[str]: ...