列表生成式:
[x**2 for x in range(10)] 从这里部分取出元素 这部分执行结果 结果放到这个列表中
>>> a= [x for x in range(10)]
>>> print(a)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> b= [x**2 for x in range(10)]
>>> print(b)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
列表生成式中放函数方法
>>> def f(n):
... return n**2
...
>>> b= [f(x) for x in range(10)]
>>> print(b)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
将列表元素或者元组元素赋值给几个变量,变量要和其中的元素个数相同
>>> s =('123','xyz',3)
>>> a,b,c = s
>>> print("a=%s,b=%s,c=%s"%(a,b,c))
a=123,b=xyz,c=3
>>> s1 = [2,3,'x']
>>> d,e,f = s1
>>> print("d=%s,e=%s,f=%s"%(d,e,f))
d=2,e=3,f=x
生成器:本身是一个可迭代的对象
生成器节约内存空间,用一次拿一次。
生成器只是一个工具,等要用的时候这个工具才会生成需要的值,这样可以节约内存,用一次才生成一次。 不能进行跳过生成,只能进行逐一生成值。
>>> s = (x*2 for x in range(10))
>>> print(s)
<generator object <genexpr> at 0x00000270ACC5C2B0>
>>> s.__next__() #函数__next__()进行生成值,等同于next(s)
0
>>> s.__next__()
2
>>> s.__next__()
4
>>> next(s) #等同于 s.__next__()
6
>>> next(s)
8
>>> next(s)
10
超过了生成器生成限制条件后会报 StopIteration
>>> s = (x*2 for x in range(5)) #此处范围为0-4
>>> next(s) # 0
0
>>> next(s) # 1
2
>>> next(s) # 2
4
>>> next(s) # 3
6
>>> next(s) # 4
8
>>> next(s) #超出范围,报错
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
使用for循环遍历生成器(for循环的作用遍历可迭代对象)
什么是可迭代对象??
对象有__iter__()方法的都是可迭代对象。
for循环的时候 for会去用next()去处理 ,同时 也做了超出范围的限制的停止迭代生成,这个过程中变量打印后就没有再被引用了 内存空间被回收
>>> s = (x*2 for x in range(5)) #生成器
>>> for i in s: # s生成器是一个可迭代的对象
... print(i)
...
0
2
4
6
8
定义生成器:
>>> def f(): #定义生成器对象
... print('OK')
... yield 1 #yield关键字
... print('OK2')
... yield 2
...
>>> g = f() #生成器赋给g变量
>>> print(g)
<generator object f at 0x000001BDAD1EC2B0>
>>> next(g) #next()方法
OK
1
>>> next(g)
OK2
2
>>> next(g) #超出范围后StopIteration
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
生成器代码执行顺序:
生成器执行到yield时就会返回对应的值完成该次的运行,下次调用接着上一次的yield后的代码继续执行,以此类推。
def fib(max):
n,a,b =0,0,1 #第3步执行
yield a #第4步执行 返回a的值,此时完成第一个next(g)生成,打印值a
while n <max-1: #第6步执行
yield b #第7步执行 返回b的值,此时完成第二个 next(g)生成,打印值b
a, b = b, a + b #第9步执行
n += 1 #第10步执行 此处完成后while循环第一轮结束第二轮开始走到 yield b的时候完成第三个next(g)生成,打印值b, 后续的继续循环生成到第9个的时报StopIteration错(此处限制只能生成8个)。
g = fib(8) #第1步执行
print(next(g)) #第2步执行
print(next(g)) #第5步执行
print(next(g)) #第8步执行
print(next(g))
print(next(g))
print(next(g))
print(next(g))
生成器传参的方法send()
>>> def f():
... a = yield 1 #传值从第二次开始
... yield a
... yield 3
...
>>> b = f()
>>> print(b.send(None)) #第一次生成时需要参数为None,没有参数
1
>>> print(b.send('what')) #输入参数what,yield返回参数a为what
what
>>> print(b.send(None))
3
注意yield关键字传值的时机。 通过send()方法传值给yield参数,第一次传入的参数为None
import time
def consumer(name):
print("%s prepares to eat the Baozi"%name)
while True:
baozi = yield
print("Baozi [%s] is coming,%s eats all"%(baozi,name))
def maker(name):
a = consumer('A') # 两个吃包子的人生成器
b = consumer('B')
a.__next__() # 生成器第一次生成时不需要输入参数
b.__next__()
print ("%s prepares to make the Baozi."%name)
for i in range(10):
time.sleep(1)
nowTime = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())
print('\nTwo Baozi have made sucessfully! %s'%nowTime)
a.send(i) # 包子轮数传值使用send()方法传入生成器在while true中循环生成
b.send(i)
maker(name='Li Lei')
例子:
def add(s, x):
return s + x
def gen():
for i in range(4):
yield i
base = gen()
for n in [1, 10]:
base = (add(i, n) for i in base)
print(list(base))
运行结果为:
[20,21,22,23]
核心语句就是:
for n in [1, 10]:
base = (add(i + n) for i in base)
在执行list(base)的时候,开始检索,然后生成器开始运算了。关键是,这个循环次数是2,也就是说,有两次生成器表达式的过程。必须牢牢把握住这一点。
生成器返回去开始运算,n = 10而不是1没问题吧,这个在上面提到的文章中已经提到了,就是add(i+n)绑定的是n这个变量,而不是它当时的数值。
然后首先是第一次生成器表达式的执行过程:base = (10 + 0, 10 + 1, 10 + 2, 10 +3),这是第一次循环的结果(形象表示,其实已经计算出来了(10,11,12,3)),然后第二次,base = (10 + 10, 11 + 10, 12 + 10, 13 + 10) ,终于得到结果了[20, 21, 22, 23].