python学习笔记--generator生成器

来源:互联网 发布:python empty 编辑:程序博客网 时间:2024/05/28 15:50

在代码中遇到了一个关键字yield,查yield遇到了generator生成器,查generator遇到了迭代。于是从后往前一点点看吧再见

迭代iteration

当我们建立了一个列表、元组或字符串时,我们能够逐个读取其中的内容,因此称之为可迭代对象。例如用列表生成式建立一个列表:

lsta=[x**2 for x in range(10)]for x in lsta:    print(x,end=' ')# 0 1 4 9 16 25 36 49 64 81 

所有能够使用for...in...语法的都是迭代器,如列表(list)、元组(tuple)、字符串(str)、字典(dict)等,它们能够存储一定数量的元素并允许在其上进行特定操作。由于每一个元素都会占用特定的内存空间,因此当数据量非常大的时候其消耗的内存空间也将很大。如果我只是想按序读取而不需要将大量的元素全部存储在内存空间,那么生成器将会是一个很好的选择。

生成器generator

生成器是可迭代的,与列表类似,不同的是:生成器仅可读取一次,因为它并没有将所有元素放到内存中,而是实时生成数据。创建一个生成器代码如下:

gena=(x**2 for x in range(10))print(gena) # <generator object <genexpr> at 0x0383FCF0>for x in gena:    print(x,end=' ')# 0 1 4 9 16 25 36 49 64 81 

看起来只是列表的[]变成了()而已,但是如下代码就能看出生成器在内存空间占用方面的优势:

import syslsta=[x**2 for x in range(10)]lstb=[x**2 for x in range(0x7ffff)]gena=(x**2 for x in range(10))genb=(x**2 for x in range(0x7ffff))print(sys.getsizeof(lsta)) # 100print(sys.getsizeof(lstb)) # 2145012print(sys.getsizeof(gena))# 48print(sys.getsizeof(genb))# 48

yield

关键字yield类似return,只是函数返回的是一个生成器。例如:

def testyield(maxn):    i=0    while i<maxn:        yield i        i+=1for i in testyield(10):    print(i,end=' ')# 0 1 2 3 4 5 6 7 8 9 

对于函数testyield(),在调用该函数的时候,其内部代码并不会立即执行,它只是返回了一个生成器对象。当使用for进行迭代的时候,函数内部的代码才会执行,具体过程如下:

第一次迭代中,函数执行到yield并返回yield后面的变量作为第一次迭代的结果,此时i的值0,第二次迭代会接着从上次执行到的位置开始,继续执行接下来的代码,即i+=1,并再次到达yield为止,此时i的值是1。直到没有可返回的值为止。

当函数执行结束时,生成器generator会自动抛出StopIteration 异常,表示迭代完成。在 for 循环里,无需处理 StopIteration 异常,循环会正常结束。代码如下:

mytest=testyield(10)while True:    mytest.__next__()

以上代码抛出异常:

Traceback (most recent call last):
  File "E:/Workplace_pycharm/testpython/test.py", line 21, in <module>
    mytest.__next__()
StopIteration



下面补充一些迭代模块

itertools迭代工具

全排列permutations

permutations可以对传入的参数进行全排列,并返回一个生成器。例如:
import itertoolsla=['A','B','C']p=(itertools.permutations(la))print(list(p))# [('A', 'B', 'C'), ('A', 'C', 'B'), ('B', 'A', 'C'), ('B', 'C', 'A'), ('C', 'A', 'B'), ('C', 'B', 'A')]

分组groupby

groupby可以把迭代器中相邻的重复元素挑出来放在一起,例如:
stra='AAAASSSSDDDDFFFFFFGGHHJKK'for key,item in itertools.groupby(stra):    print(key,list(item))# A ['A', 'A', 'A', 'A']# S ['S', 'S', 'S', 'S']# D ['D', 'D', 'D', 'D']# F ['F', 'F', 'F', 'F', 'F', 'F']# G ['G', 'G']# H ['H', 'H']# J ['J']# K ['K', 'K']

无限迭代count

count(start)返回以start为起点的自然数列,例如:
genCount=itertools.count(3)for x in genCount:    print(x,end=' ')#3 4 5 6 7 .... 停不下来

无限迭代cycle

cycle(iter)会将传入的迭代器无限重复,例如:

genCycle=itertools.cycle('ASDF')for x in genCycle:    print(x,end=' ')# A S D F A S D F S A D F ... 停不下来

无限迭代repeat

repeat()将传入的参数无限重复,若指定第二个参数(重复次数)则重复有限次,例如:

genReapeat=itertools.repeat('ASDF',3)for x in genReapeat:    print(x,end=' ')# ASDF ASDF ASDF


原创粉丝点击