在代码中遇到了一个关键字yield,查yield遇到了generator生成器,查generator遇到了迭代。于是从后往前一点点看吧
当我们建立了一个列表、元组或字符串时,我们能够逐个读取其中的内容,因此称之为可迭代对象。例如用列表生成式建立一个列表:
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
生成器是可迭代的,与列表类似,不同的是:生成器仅可读取一次,因为它并没有将所有元素放到内存中,而是实时生成数据。创建一个生成器代码如下:
gena=(x**2 for x in range(10))
print(gena) # at 0x0383FCF0>
for x in gena:
print(x,end=' ')
# 0 1 4 9 16 25 36 49 64 81
import sys
lsta=[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)) # 100
print(sys.getsizeof(lstb)) # 2145012
print(sys.getsizeof(gena))# 48
print(sys.getsizeof(genb))# 48
关键字yield类似return,只是函数返回的是一个生成器。例如:
def testyield(maxn):
i=0
while i
第一次迭代中,函数执行到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
mytest.__next__()
StopIteration
下面补充一些迭代模块
permutations可以对传入的参数进行全排列,并返回一个生成器。例如:
import itertools
la=['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可以把迭代器中相邻的重复元素挑出来放在一起,例如:
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']
genCount=itertools.count(3)
for x in genCount:
print(x,end=' ')
#3 4 5 6 7 .... 停不下来
genCycle=itertools.cycle('ASDF')
for x in genCycle:
print(x,end=' ')
# A S D F A S D F S A D F ... 停不下来
repeat()将传入的参数无限重复,若指定第二个参数(重复次数)则重复有限次,例如:
genReapeat=itertools.repeat('ASDF',3)
for x in genReapeat:
print(x,end=' ')
# ASDF ASDF ASDF