参考:
语言参考 3.1. Objects, values and types https://docs.python.org/3.7/reference/datamodel.html#objects-values-and-types
标准库 8.4. https://docs.python.org/3.6/library/collections.abc.html#module-collections.abc - Abstract Base Classes for Containers
Iterables vs. Iterators vs. Generators https://nvie.com/posts/iterators-vs-generators/
完全理解 Python 迭代对象, 迭代器, 生成器 http://python.jobbole.com/87805/
在某些对象中会包含对其它对象的引用, 这样的对象被称作容器(containers). 因此, 我们可以把容器视作用于组织各种元素的数据结构.
下面是一些常见的容器对象:
list, deque, ...
set, frozensets, ...
dict, defaultdict, OrderedDict, Counter, ...
tuple, namedtuple, ...
str
另外, 容器是存储在内存中的数据结构, 并且通常会将全部的值都保存在内存中(也有一些特例, 并不是所有的元素都放在内存, 比如迭代器和生成器对象).
在某些对象中会包含对其它对象的引用, 这样的对象被称作容器 (containers). 元组, 列表, 字典都属于容器. 部分容器值可能是指向其它对象的引用. 在大多数情况下, 当谈到某个容器的值时, 我们谈论的仅是值, 而不是所包含的对象的 ID(identities); 但是, 在讨论容器的可变性时, 则只是在谈论容器中直接包含的对象的 ID. 因此, 如果不可变容器(比如, 元组) 中包含了对可变对象的引用, 那么当被引用的可变对象发生改变时, 相应的容器值也将发生改变.
从技术角度来说, 容器是实现了 __contains__ 方法的对象, 也就是说容器对象肯定可以执行成员测试.
- import collections.abc as abc
- class Fib(object):
- def __reset(self):
- self.a = 1
- self.b = 1
- def __init__(self):
- self.__reset()
- def __contains__(self, item):
- print("调用 __contains__")
- self.__reset()
- while True:
- self.a, self.b = self.b, self.a + self.b
- if item == self.a:
- return True
- elif item < self.a:
- return False
- a_fib = Fib()
- assert isinstance(a_fib, abc.Container)
注意: 尽管绝大多数容器都提供了某种方式来获取其中包含的每一个元素, 但这并不是容器本身提供的能力, 而是 iterable 赋予了容器这种能力. 容器并不一定都是 iterable, 比如: Bloom filter https://zh.wikipedia.org/wiki/布隆过滤器 , 虽然 Bloom filter 可以检测某个元素是否存在于容器中, 但是并不能从容器中获取其中的每一个值, 因为 Bloom filter 并没有把元素存储在容器中, 而是通过一个散列函数映射成一个值保存在数组中.
来源: http://www.jianshu.com/p/63af3680c221