python3.6入门到高阶(全栈) day012 生成器

今日主要内容(重要)
迭代器
__iter__() 获取迭代器
__next__() 下一个

生成器
本质就是迭代器
两种方式写生成器
1. 生成器函数
2. 生成器表达式

生成器函数
函数内部有yield. yield返回 -> return
yield可以把函数分段执行
生成器函数被调用的时候. 返回生成器
def func():
yield
g = func() - 得到生成器
def func():
print("111")
yield 222
gener = func() # 这个时候函数不会执⾏. ⽽是获取到⽣成器
ret = gener.__next__() # 这个时候函数才会执⾏. yield的作⽤和return⼀样. 也是返回
数据
print(ret)
结果:
111
222
# 那么我们可以看到, yield和return的效果是⼀样的. 有什么区别呢?
yield是分段来执一个函数. return呢? 直接停止执行函数.

生成器的用法和迭代器基本一致
__next__() 开始执行生成器 . 执行到yield. 直到没有yield.
抛出StopIteration

send() 可以给上一个yield传值
def eat():
print("我吃什么啊")
a = yield "馒头"
print("a=",a)
b = yield "⼤饼"
print("b=",b)
c = yield "⾲菜盒⼦"
print("c=",c)
yield "GAME OVER"
gen = eat() # 获取⽣成器
ret1 = gen.__next__()
print(ret1)
ret2 = gen.send("胡辣汤")
print(ret2)
ret3 = gen.send("狗粮")
print(ret3)
ret4 = gen.send("猫粮")
print(ret4)
send和__next__()区别:
1. send和next()都是让⽣成器向下走⼀次
2. send可以给上一个yield的位置传递值, 不能给最后一个yield发送值.
在第一次执行生成器代码的时候不能使用send()

1. 省内存
2. 惰性机制, 不访问__next__() 就没有值.
3. 只能向前. 不能反复.


各种推导式(简单)
列表推导式 [ 结果 for 变量 in 可迭代对象 if 条件]
lst =[]
for i in range(1,18)
lst.append(i)
print(lst)
替换成列表推到式
lst =[i for i in range(1,18)]
print(lst)

例 # [3,6,9] 已知
# [(1,2,3), (4,5,6), (7,8,9)]
# lst = [3,6,9]
# new_lst = [(el-2, el-1, el) for el in lst]

# for el in lst: # 3
# new_lst.append((el-2, el-1, el))
# print(new_lst)

例 # 寻找名字中带有两个e的⼈的名字 name.count("e") == 2
# names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven','Joe'],
# ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
#
# lst = [name for el in names for name in el if name.count("e") == 2]
# print(lst)

字典推导式 {key: value for循环 if判断}
例 # lst = [11, 22, 33] # => {0:11, 1:22, 2:33}
# dic = {i:lst[i] for i in range(len(lst)) }
# print(dic)

例 # dic = {"张无忌":"赵敏", "杨过":"小龙女", "郭靖":"黄蓉"}
# 把字典中的key和value互换
# dic = {"赵敏":"张无忌", "小龙女":"杨过", "黄蓉":"郭靖"}
# dic1 = { v:k for k, v in dic.items()} # 强化
# print(dic1)
#
# dic2 = { dic[k]:k for k in dic} # 强化
# print(dic2)

集合推导式 {key for循环 if判断}
# 集合推导式 # 不可变. 不重复, 无序
# {结果 for循环 if判断}
# s = {i*"胡辣汤" for i in range(10)}
# print(s)

生成器表达式(最难)
(结果 for循环 if判断)
惰性机制, 不访问__next__() 就没有值.
只能向前. 不能反复.

例 def func():
print(111)
yield 222
g = func() # 生成器g
g1 = (i for i in g) # 生成器g1. 但是g1的数据来源于g
g2 = (i for i in g1) # 生成器g2. 来源g1
print(list(g)) # 获取g中的数据. 这时func()才会被执⾏. 打印111.获取到222. g完毕.
print(list(g1)) # 获取g1中的数据. g1的数据来源是g. 但是g已经取完了. g1 也就没有数据

print(list(g2)) # 和g1同理
### list 具有 __next__ 效果
for循环的机制
for i in [1,2,3]:
print(i)
使⽤while循环+迭代器来模拟for循环
lst = [1,2,3]
lst_iter = lst.__iter__()
while True:
try:
i = lst_iter.__next__()
print(i)
except StopIteration:
break
###

yield from

例 def gen():
lst = ["⿇花藤", "胡辣汤", "微星牌饼铛", "Mac牌锅铲"]
lst2 = ["饼铛还是微星的好", "联想不能煮鸡蛋", "微星就可以", "还可以烙饼"]
yield from lst
yield from lst2
g = gen()
for el in g:
print(el)
效果:
麻花藤
胡辣汤
微星牌饼铛
Mac牌锅铲
饼铛还是微星的好
联想不能煮鸡蛋
微星就可以
还可以烙饼
posted @ 2018-11-01 18:42  曾经有个贵族  阅读(137)  评论(0编辑  收藏  举报