究竟什么是“容器"?在蟒蛇?(以及所有的 python 容器类型是什么?)

2022-01-24 00:00:00 python containers

问题描述

python 文档经常提到容器".例如:

The python documentation frequently speaks of "containers". E.g. :

如果 check_circular 为 False(默认:True),则循环容器类型的引用检查将被跳过并循环引用将导致溢出错误(或更糟).

If check_circular is False (default: True), then the circular reference check for container types will be skipped and a circular reference will result in an OverflowError (or worse).

但我找不到任何容器的官方定义,也找不到它们的列表.

But I can't find any official definition of containers, neither a list of them.

对于 Python 2.7.3:

For Python 2.7.3:

检查的内置类型是容器:

(isinstance(object, collections.Container) 返回 True)

  1. 定义了 __contains__ 方法的容器:

  • 所有内置序列类型:列表、字节数组、字符串、unicode 字符串和元组.
  • 字典
  • 所有内置集合类型:集合和frozensets

没有定义 __contains__ 方法的容器:

Containers which do not have a __contains__ method defined:

  • xrange 对象

检查的不是容器的内置类型:

(isinstance(object, collections.Container) 返回 False):

  • Int 对象
  • 浮动对象
  • 长对象
  • 布尔对象
  • 模块对象
  • 文件对象
  • 缓冲区对象
  • 无对象

告诉我您检查了哪些其他内置类型 isinstance(object, collections.Container),我会将它们添加到列表中.

Tell me which other builtin types you have checked for isinstance(object, collections.Container) and I'll add them to the list.


解决方案

容器是包含任意数量的其他对象的任何对象.通常,容器提供了一种访问所包含对象并对其进行迭代的方法.

Containers are any object that holds an arbitrary number of other objects. Generally, containers provide a way to access the contained objects and to iterate over them.

容器示例包括tuplelistsetdict;这些是内置容器.collections 模块.

Examples of containers include tuple, list, set, dict; these are the built-in containers. More container types are available in the collections module.

严格来说,collections.abc.Container 抽象基类(collections.Python2 中的 Container)适用于通过 __contains__ 魔术方法支持 in 运算符的任何类型;所以如果你可以写 x in y 那么 y 通常是一个容器,但并不总是:容器之间的一个重要区别点 和一般的 iterables 是,当迭代时,容器将返回它们持有引用的现有对象,而生成器和例如file 对象每次都会创建一个新对象.这对垃圾收集和深度对象遍历(例如 deepcopy 和序列化)有影响.

Strictly speaking, the collections.abc.Container abstract base class (collections.Container in Python2) holds for any type that supports the in operator via the __contains__ magic method; so if you can write x in y then y is usually a container, but not always: an important point of difference between containers and general iterables is that when iterated over, containers will return existing objects that they hold a reference to, while generators and e.g. file objects will create a new object each time. This has implications for garbage collection and deep object traversal (e.g. deepcopy and serialisation).

举个例子,iter(lambda: random.choice(range(6)), 0)支持in操作符,但肯定是不 一个容器!

As an example, iter(lambda: random.choice(range(6)), 0) supports the in operator, but it is certainly not a container!

Collections.abc.Container 抽象基类的意图是只考虑 __contains__ 魔术方法,而不考虑支持 in 操作符是一个真正的容器应该能够在单个操作中测试容器,并且不会显着改变内部状态.由于 Collections.abc.Container__contains__ 定义为抽象方法,因此可以保证如果 isinstance(x, collections.abc.Container)x 支持 in 运算符.

The intent of the Collections.abc.Container abstract base class in only considering the __contains__ magic method and not other ways of supporting the in operator is that a true container should be able to test for containment in a single operation and without observably changing internal state. Since Collections.abc.Container defines __contains__ as an abstract method, you are guaranteed that if isinstance(x, collections.abc.Container) then x supports the in operator.

实际上,所有容器都将具有 __contains__ 魔术方法.然而,当测试一个对象是否是一个容器时,你应该使用 isinstance(x, collections.abc.Container) 来清晰和向前兼容,如果 Container 子类检查是改变了.

In practice, then, all containers will have the __contains__ magic method. However, when testing whether an object is a container you should use isinstance(x, collections.abc.Container) for clarity and for forward compatibility should the Container subclass check ever be changed.

相关文章