类型注释中的 collections.Iterable 与 typing.Iterable 和检查 Iterable

Ben*_* Du 26 python types annotations iterable isinstance

我发现,在Python都collections.Iterabletyping.Iterable在类型注释,并检查对象是否是迭代的,即可以使用,无论是isinstance(obj, collections.Iterable)isinstance(obj, typing.Iterable)作品。我的问题是,它们之间有什么区别?在哪些情况下更喜欢哪一个?

gil*_*lch 27

typing.Iterable是通用的,因此您可以在类型注释中说明它是可迭代的,例如Iterable[int]对于整数的可迭代。

可迭代的集合是一个抽象基类。这些可以包括额外的 mixin 方法,以便在您创建自己的子类时使接口更容易实现。

现在碰巧Iterable不包含任何这些mixin,但它是其他抽象基类的接口的一部分。

从理论上讲,输入可迭代对象对两者都适用,但它使用了一些奇怪的元类魔法来做到这一点,因此它们在所有情况下的行为方式并不完全相同。在运行时你真的不需要泛型,所以没有必要在类型注释等之外使用它。可迭代的集合作为超类不太可能引起问题。

所以简而言之,您应该在类型注释中使用类型可迭代,但可将集合作为超类使用。


更新:

由于PEP 585,从版本 3.9 开始,Python 的标准库容器类型也将能够接受类型注释的通用参数。这包括collections.abc.Iterable类。当仅支持 Python 3.9 或更高版本时,不再有任何理由使用typing.Iterable,并且typing不推荐使用from 导入任何这些容器类型。

  • 3.9以下的怎么样?在 3.8 中,我不能使用 `collections.abc.Iterable[T]`,只有 `typing.Iterable[T]` 可以,但是 api 说 `typing.Iterable[T]` 将在 3.9 中被弃用。我认为这很混乱 (4认同)
  • 为了补充您关于 Pep 585 的观点,“typing.List[T]”将简单地替换为“list[T]” (3认同)
  • @小文件,是的,这就是“弃用”的意思。不过,您必须以旧的方式做事才能保持与旧版本的兼容性。一旦他们最终删除它,您将不得不放弃对旧版本的支持或找到解决方法,例如向后移植。 (3认同)