python迭代器与生成器

以下都是我自学Python整理的笔记,以便帮助学习。

容器(container)

  1.容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个的迭代获取,可以用in,not in关键字判断元素是否在容器中。通常这类数据结构把所有的元素存储在内存中(也有一些特例并不是把所有的元素存在内存,比如迭代器和生成器对象)在python中,常见的容器对象有:list,set,dict,tuple,str...

  2.尽管绝大多数容器都提供了某种方式来获取其中的每一个元素,但这并不是容器本身提供的能力,而是**可迭代对象**赋予了容器这种能力,当然并不是所有的容器都是可迭代的,比如:[Bloom filter],虽然Bloom filter可以用来检测某个元素是否包含在容器中,但是并不能从容器中获取其中的每一个值,因为Bloom filter压根就没把元素存储在容器中,而是通过一个散列函数映射成一个值保存在数组中。

可迭代对象(iterable)

  1.许多容器都是可迭代对象,但也有很多不是容器的对象也是可迭代对象,比如处于打开状态的files,socket等。

  2.可迭代对象都具有__iter__函数,并且可迭代对象通过iter()函数会返回一个迭代器,迭代器内部具有一个状态,该状态用于记录当前迭代所在的位置方便下一次迭代。

  3.迭代器有一种具体的迭代器类型,比如list_iterator,set_iterator。可迭代对象实现了__iter__方法,该方法返回一个迭代器对象。

迭代器(iterator)

  1.迭代器是一种带状态的对象,它能在你调用next()方法的时候返回容器中的下一个值,任何实现了__iter__和__next__方法的对象都是迭代器,__iter__返回迭代器本身,__next__返回容器中的下一个值,当遍历到最后一个值,没有元素的时候会抛出StopIteration异常。

  2. itertools函数返回的都是迭代器对象。

  3.迭代器不会一次性把所有元素加载到内存,而是需要的时候才生成返回结果。迭代器就像一个懒加载的工厂,等到有人需要的时候才给它生成值返回,没调用的时候就处于休眠状态等待下一次调用。

  4.三种常见的迭代器:

  (1)无限迭代器,这个可以理解成一条无限延长的直线。

   itertools模块下的count(start)函数,star为起点。

help(itertools.count)#查看帮助文档 
count(start=0, step=1) --> count object | Return a count object whose .__next__() method returns consecutive values. def count(firstval=0, step=1): | x = firstval | while 1: | yield x | x += step

例子:

import itertools
>>> counter = itertools.count(start=2)
>>> next(counter)
2
>>> next(counter)
3
>>> next(counter)
4

 (2)通过一个有限序列生成无限迭代器,这个可以理解为是一个圆,无限遍历。

   itertools下的cycle(iterable)函数,参数是一个可迭代对象。

help(itertools.cycle)
cycle(iterable) --> cycle object
 |  Return elements from the iterable until it is exhausted.
 |  Then repeat the sequence indefinitely.
 #从可迭代对象取出所有的元素然后无限循环

例子:

>>> from itertools import cycle
>>> colors = cycle(['red','white','blue'])
>>> next(colors)
'red'
>>> next(colors)
'white'
>>> next(colors)
'blue'
>>> next(colors)
'red'
>>> next(colors)
'white'

 (3)有限迭代器,其实就是无限迭代器中截取一段序列。

   itertools下的islice(iterable, start, stop[, step])

   iterable为可迭代对象,start为起点,不给start值时,默认从0开始,给值时会默认从起点的下一个元素开始遍历,stop为终点,step为步长。

help(itertools.islice)
class
islice(builtins.object) | islice(iterable, stop) --> islice object | islice(iterable, start, stop[, step]) --> islice object #返回一个迭代器,iterable可迭代对象,start如果不设置为0,设置了会默认从start下一个元素开始遍历,stop终止,step步长。

例子:

>>> from itertools import islice
>>> num = cycle((1,2,3))
>>> limited = islice(num,0,4)
>>> next(limited)
1
>>> next(limited)
2
>>> next(limited)
3
>>> next(limited)
1
>>> next(limited)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

生成器(generator)

  1.生成器是一种特殊的迭代器,不过这种迭代器更加优雅。需要一个yiled关键字。 生成器一定是迭代器(反之不成立),因此任何生成器也是以一种懒加载的模式生成值。

  2.生成器有延迟作用,就是有需要的时候才会生产数据,不是立即产生结果。

  生成器只能遍历一次。

  4.两种方法得到生成器:

  (1)定义生成器函数,返回值用yield而不是return,yield和return最本质的区别在于return会终止函数,不会保留函数中的变量,再次如果再次调用函数时从头开始;而yield相当于在是冻结函数,给了函数一个状态,让他暂时挂起保留此次调用的变量,下一次继续这个位置调用。

看例子:

#用return
def
func(var): while var > 0: print(var) return var var -= 1 d = func(10) print(type(d)) 10 <class 'int'>
#用yield
def func(var):
    while var > 0: 
        yield var
        #return var
        var -= 1
        
d = func(10)
print(type(d))

<class 'generator'>#type看到d是一个生成器

#所以我们可以对d进行for循环遍历
for i in d:
  print(i)
10
9
8
7
6
5
4
3
2
1

  (2)生成器表达式:把列表推导式的[ ]改成( )

    使用生成器表达式取代列表推导式可以同时节省 cpu 和 内存(RAM)。

    gen = (i for i in range(10))

gen = (i for i in range(10))
print(type(gen))
for var in gen:
    print(var)
<class 'generator'>
0
1
2
3
4
5
6
7
8
9

 

  

 

posted @ 2018-09-30 11:47  Kmnskd  阅读(329)  评论(0编辑  收藏  举报