collections.Iterable vs typing.Iterable在类型注释和检查Iterable时的区别

72

我发现在Python中,collections.Iterabletyping.Iterable都可以在类型注解和检查对象是否可迭代方面使用,即isinstance(obj, collections.Iterable)isinstance(obj, typing.Iterable)都可以。我的问题是,它们之间有什么区别?哪种更适合哪些情况?

1个回答

84
由于PEP 585 - 标准集合中的类型提示泛型, Python的标准库容器类型也能够接受一个泛型参数用于类型注释,包括collections.abc.Iterable类。
当只支持Python 3.9或更高版本时,完全没有理由使用typing.Iterable了,并且从typing导入任何这些容器类型都已经被弃用。
对于较旧的Python版本: typing.Iterable是泛型的,因此您可以在类型注释中指定它的可迭代项,例如Iterable[int]表示整数的可迭代项。
collections可迭代对象是一个抽象基类。这些可以包含额外的混入方法,以使接口在创建自己的子类时更容易实现。
现在偶然发生的是,Iterable不包括任何这些混入项,但它是其他抽象基类的接口的一部分,这些抽象基类包括这些混入项。
理论上,typing可迭代对象适用于任何情况,但它使用一些奇怪的元类魔法来实现,因此它们在所有情况下的行为都不完全相同。在运行时,您真的不需要泛型,因此除了类型注释等情况外,永远不需要使用它。作为超类,collections可迭代对象更不容易引起问题。

简而言之,在类型注释中应使用typing可迭代对象,但将collections可迭代对象用作超类。


6
补充一下你关于Pep 585的观点,typing.List[T]将被简单地替换为list[T] - BallpointBen
4
对于小于3.9版本怎么处理?在3.8中,我无法使用collections.abc.Iterable[T],只有typing.Iterable[T]可以,但是API说typing.Iterable[T]将在3.9中被弃用。我认为这很混乱。 - fishshrimp鱼虾爆栈
2
@小文件,是的,这就是“弃用”的意思。你必须按照旧的方式来做,以保持与旧版本的兼容性。一旦他们最终删除它,你将不得不放弃对旧版本的支持或找到一个解决方法,比如回溯。 - gilch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接