容器(container)
容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个地迭代获取,可以用in, not in关键字判断元素是否包含在容器。通常这类数据结构把所有的元素存储在内存中(也有一些特例,并不是所有的元素都放在内存里,比如迭代器和生成器对象,在获取的时候直接生成),在python中,常见的容器对象有:
(1) list, deque, ...
(2) set, frozensets, ...
(3) dict, defaultdict, OrderedDict, Counter, ...
(4) tuple, namedtuple, ...
(5) str
容器可以看做是一个盒子,里面可以塞任何东西。从技术角度来说,当他可以用来询问某个元素是否版旱灾其中时,那么这个对象就可以认为是一个容器,比如list, set, tuple都是都是容器对象
尽管绝大多数容器都提供了某种方式来获取其中的每一个元素,担这并不是容器本身提供的能力,而是可迭代对象赋予了容器这种能力,当然并不是所有的容器都是可迭代的,比如Bloom filter,虽然Bloom filter可以用来检测某个元素是否包含在容器中,但是并不能从容器中获取其中的每一个值,因为Bloom filter并没有把元素存储在容器中,而是通过一个散列函数映射成一个值保存在数组中。
可迭代对象(iterable)
除了大多数容器以外,还有更多的对象也是可迭代对象,比如处于打开状态的files, sockets等等。但凡是可以返回一个迭代器的对象都可以称之为可迭代对象。可迭代对象和容器一样是一种通俗的叫法,并不是指某种具体的数据类型,list是可迭代对象,set也是可迭代对象。迭代器内部持有一个状态,该状态用于记录当前迭代所在的位置,以方便下次迭代的时候获取正确的元素。迭代器有一种具体的迭代器类型,比如list_iterator, set_iterator。可迭代对象实现了__iter__方法,该方法返回一个迭代器对象。
迭代器(iterator)
迭代器是一个带状态的对象,它能在你调用next()方法的时候返回容器中的下一个值,任何实现了__iter__和__next__()(python2中实现next())方法的对象都是迭代器,__iter__返回迭代器自身,__next__返回容器中的下一个值,如果容器中没有更多元素了,则抛出StopIteration异常。
迭代器就是实现了工厂模式的对象,它在你每次你询问下一个值的时候给你返回。有很多关于迭代器的例子,比如itertools函数返回的都是迭代器对象。
生成无限序列:
从一个有限序列中生成无线序列:
从无限的序列中生成有限序列:
自定义一个生成器,以斐波那契数列为例:
Fib既是一个可迭代对象(因为它实现了__iter__方法),又是一个迭代器(因为它实现了__next__方法)。实例变量prev和curr用户维护迭代器内部的状态。每次调用next()方法的时候做两件事:
1.为下一次调用next方法修改状态
2.为当前这次调用生成返回结果
迭代器就像一个懒加载的工厂,等到有人需要的时候才给它生成值返回,没调用的时候就处于休眠状态等待下一次调用。
生成器(generator)
生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。它不需要再像上面的类一样写__iter__()和__next__()方法了,只需要一个yield关键字。生成器一定是迭代器(反之不成立),因此任何生成器也是以一种懒加载的模式生成值。用生成器来实现斐波那契数列的例子是:
fib就是一个普通的python函数,它特殊的地方在于函数中没有return关键字,函数的返回值是一个生成器对象。当执行f = fib()返回的是一个生成器对象,此时函数体中的代码并不会执行,只有显示或隐式调用next的时候才会真正执行里面的代码。
生成器在python中是一个非常强大的编程结构,可以用更少的中间变量写流式代码。此外,相比其他容器对象它更能节省内存和cpu,它可以用更少地代码来实现相似的功能。如以下使用生成器函数完成的功能替换:
生成器表达式(generator expression)
生成器表达式是列表推导式的生成器版本,看起来像列表推导式,但是它返回的是一个生成器对象而不是列表对象。
总结:
1. 容器是一系列元素的集合,str、list、set、dict、file、sockets对象都可以看作是容器,容器都可以被迭代(用在for,while等于语句中),因此他们被称为可迭代对象。
2.可迭代对象实现了__iter__方法,该方法返回一个迭代器对象。
3.迭代器持有一个内部状态的字段,用于记录下次迭代返回值,他实现了__next__和__iter__方法,迭代器不会一次性把所有元素加载到内存,而是需要的时候才生成返回结果。
4.生成器是一种特殊的迭代器,它的返回值不是通过return而是用yield。