一. 推导式
列表, 字典, 集合有推导式, 元组没有推导式
列表推导式: lst = [i for i in range(10) if i % 2 == 0]
字典推导式: dic = {k:v for k,v in func() if k>v} # def func(): yield 2,1 yield 3,1 yield 4,1 (yield 的第一个值不能相同, 因为字典的键会传不进去)
集合推导式: se = {i for i in range(5)}
a = (i for i in range(10) # 这不是元组, 这是生成器的表达式, 具有惰性.
可以用for循环, while循环, list[], tuple(), set(), 来遍历生成器
二. 生成器
生成器的本质是迭代器
生成器的特点和迭代器一样, 取值方式一样, __next__(), send(), send()可以给上一个yield传值
生成器一般由生成器函数或生成器表达式来创建
超过yield的个数会报错, 但可以用try: except StopIteration兜着
生成器函数:
和普通函数没有区别, 函数里面含有yield.
生成器函数在执行时, 默认不会执行函数, 而是返回生成器
生成器函数通过生成器的__next__()分段执行这个函数.
可以用send()给上一个yield传值, 不能在开头(没有上一个yield)
f = func()拿到的是生成器, 不会执行函数.
yield会停止执行函数, 下次再分段执行函数.
如果不使用f = func()来获取生成器, 每次用func().__next__()来获取, 每次都是获取的到第一个yield的值
def func():
a = yield 1
print(a)
b = yield 2
print(b)
c = yield 3
print(c)
yield 4
f = func()
# ===================================== 第一个输出方法 =====================================
print(f.__next__())
print(f.send(123))
print(f.send(234))
print(f.send(345))
输出
1
123
2
234
3
345
4
# ===================================== 第二个输出方法 =====================================
print(f.__next__(),f.send(123),f.send(234),f.send(345))
输出:
123
234
345
1 2 3 4
生成器表达式:
gen = (i for i in range(10) if i >= 5)
gen = (func(i) for i in range(10) if i >= 5)
gen = ('xxxxx{}".format(i) for i in range(10))
特性:
惰性机制
只能向前
节省内存
题:
def func():
print(111)
yield 222
yield 333
g = func()
g1 = (i for i in g) # g1拿到的还生成器表达式, 不会执行表达式, 在后面的list(g1)才会执行表达式
g2 = (i for i in g)
print(list(g)) # list(g)拿到的是g的所有的yield的值, 本来g是不会自动执行的, 但是list使g
# 自动执行了, g执行完了以后, g是生成器, 不能回退, 所以g1和g2再执行g的时候
# 就拿不到值了
print(list(g1))
print(list(g2)) # 如果g2先执行, g2就会遍历完g中的值, list又会便利完g2的值, 所以g1再遍历g
# 的值, 或者list再遍历g的值就拿不到值了
def add(a, b):
return a + b
def test():
for i in range(4):
yield i # yield 0,1,2,3
g = test()
for n in [2,10]
g = (add(n, i) for i in g) # 拿到g时不会遍历生成器
print(list(g))
# ===================================== g的运行 =====================================
for n in [2,10]
g = (add(n, i) for i in g)
n = 2
# g = (add(n = 2, i) for i in g) # i的值现在拿不出来, 因为g没有被遍历, 所以add函数无法执行
# 所以add函数还是add(n, i)
n = 10
# g = (add(n = 10, i) for i in (add(n = 10, i) for i in g)) # 由于add函数的n上次未执行,
# 所以add函数还是add(n, i), 所以这次n = 10时, n就被重新
# 赋值了
list(g)
# g = add(10, i) for i in (add(10, i) for i in 0.1.2.3))
# ===================================== 改一下 =====================================d
def add(a, b):
return a + b
def test():
for i in range(4):
yield i # yield 0,1,2,3
g = test()
for n in [2,10]
g = [add(n, i) for i in g]
print(list(g))
# ===================================== g的运行 =====================================
n = 2
g = [2,3,4,5] # 列表的推导式, 不是生成器的表达式
n = 10
g = [12,13,14,15]