转载请注明出处:https://www.jianshu.com/u/5e6f798c903a
参考:
- 语言参考 3.1. Objects, values and types
- 标准库 8.4.
collections.abc
— Abstract Base Classes for Containers- Iterables vs. Iterators vs. Generators
- 完全理解 Python 迭代对象、迭代器、生成器
在某些对象中会包含对其它对象的引用,这样的对象被称作容器(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 ,虽然 Bloom filter 可以检测某个元素是否存在于容器中,但是并不能从容器中获取其中的每一个值,因为 Bloom filter 并没有把元素存储在容器中,而是通过一个散列函数映射成一个值保存在数组中。