Python生成器
1 def f(n): 2 return n**3 3 4 #列表生成式 5 a = [f(x) for x in range(10)] 6 7 print (a) 8 print(type(a)) 9 10 11 12 13 14 15 t = ('123', 8)#元组 16 a, b = t # a=t[0], b=t[1] ,数量必须一致 17 print(a) 18 print(b)
执行结果:
[0, 1, 8, 27, 64, 125, 216, 343, 512, 729] <class 'list'> 123 8 Process finished with exit code 0
生成器
任何使用yield的函数都称之为生成器
使用yield,可以让函数生成一个序列,该函数返回的对象类型是"generator",通过该对象连续调用__next__()方法返回序列值。
生成器函数只有在调用__next()__方法的时候才开始执行函数里面的语句,比如:
def count(n): print ( "cunting" ) while n > 0: yield n #生成值:n n -= 1 print("hi") c = count(5) h = c.__next__() # 到yield后不执行 print(h) l = c.__next__() # 从上一次yield后开始执行 print(l) print(10*"==") generator = count(6) for i in generator: print(i) print(generator) # 任何使用yield的函数都称之为生成器
执行结果:
cunting 5 hi 4 ==================== cunting 6 hi 5 hi 4 hi 3 hi 2 hi 1 hi <generator object count at 0x7f42cb3980a0> Process finished with exit code 0
在调用count函数时:c=count(5),并不会打印"counting"只有等到调用c.__next__()时才真正执行里面的语句。每次调用__next__()方法时,count函数会运行到语句yield n处为止,__next__()的返回值就是生成值n,再次调用__next__()方法时,函数继续执行yield之后的语句
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器(Generator)。
要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]
改成()
,就创建了一个generator:
1 s = (x*2 for x in range(5)) #生成器 2 3 print(s) # <generator object <genexpr> at 0x7f510c34a360> 4 5 print(next(s)) # 等价于 s.__next__() 0 6 7 print(next(s)) # 只能按顺序取值 8 9 print(next(s))
执行结果
<generator object <genexpr> at 0x7fc5b2af5360> 0 2 4 Process finished with exit code 0
生成器一共两种创建方式:
1.s = (x*2 for x in range(5)) 而列表生成器为[x*2 for x in range(5)]
2. yield
1 def foo(): 2 print('ok1') # foo()时不会被执行 3 yield 1 4 5 print("ok2") 6 yield 2 7 8 9 g=foo() #生成生成器对象 10 print(g) # foo()成为了生成器对象 <generator object foo at 0x7fc04a8d4360> 11 12 a = next(g) #进入生成器,yield相当于return,执行到yield不会再向下执行 13 14 b = next(g) #到yield 1,再print ('ok2') 15 print(a) 16 print(b) 17 18 19 print("\n") 20 21 for i in foo(): # i 是返回值 1, 2 22 print(i)
执行结果:
<generator object foo at 0x7f8fb17d5360> ok1 ok2 1 2 ok1 1 ok2 2 Process finished with exit code 0
什么是可迭代对象(对象拥有iter方法的)
l = [1, 2, 3] l.__iter__()
send
1 def bar(): 2 print('ok') 3 count = yield 1 #yield先返回 4 print(count) 5 6 yield 2 7 8 b = bar() 9 10 s = b.send(None) #相当于next(b) 第一次send前如果没有next,只能传一个send(None),并不知道将值传给谁,只能用None 11 print(s) #yield返回值 12 13 ret = b.send('eeee') #传给count 14 print(ret)
可以断点执行(debug),了解具体的执行过程,第10行返回1(yield 1,s为1),第13行(count = 'eeee'),并且print(count),yield 2返回2,ret为2。
执行结果:
ok 1 eeee 2 Process finished with exit code 0