容器是包含任意数量其他对象的任何对象。通常,容器提供了一种访问包含的对象并对其进行迭代的方法。
容器的实例包括tuple
,list
,set
,dict
; 这些是 内置容器 。collections
模块中提供更多容器类型。
严格来说,collections.abc.Container
抽象基类(collections.Container
在Python2中)适用于in
通过__contains__
magic方法支持运算符的任何类型。因此,如果可以写的x in y
话y
, 通常是 一个容器,但并不总是这样: 容器 与一般 可迭代 对象之间的重要区别在于,当进行迭代时,容器将返回它们持有引用的现有对象,而生成器和file
对象(例如)将创建每次都有一个新对象。这对垃圾收集和深度对象遍历(例如deepcopy
和序列化)具有影响。
例如,iter(lambda: random.choice(range(6)), 0)
支持in
操作员,但它肯定 不是 容器!
的的意图Collections.abc.Container
抽象基类中只考虑了__contains__
魔术方法,而不是相配套的其他方式in
运算符是一个真正的容器应能测试围堵在一个单一的操作,并没有观察地改变内部状态。由于Collections.abc.Container
定义__contains__
为抽象方法,因此可以保证ifisinstance(x, collections.abc.Container)
然后x
支持in
运算符。
因此,实际上,所有容器都将具有__contains__
魔术方法。但是,在测试对象是否为容器时,应该使用它isinstance(x, collections.abc.Container)
来保持清晰度和向前兼容性,并且应该Container
更改子类检查。