一, 生成器.
二, 生成器函数
三, 各种推导式.
四, 生成器表达式.
一, 生成器.
生成器本质就是个迭代器, 一个一个的创建对象,
创建生成器的方式:
1. 生成器函数
2. 通过生成器表达式来获取生成器
3. 类型转换
二, 生成器函数.
什么是生成器函数: 函数中包含了 yield, 此函数就是生成器函数, 我们执行函数的时候, 就是获取这个生成器. 而不再是执行函数内容.
举例说明
- def func():
- print("111")
- return 222
- ret = func()
- print(ret)
结果:
111 222
再将函数中的 return 换成 yield 就是生成器
- def func():
- print("111")
- yield 222
- ret = func()
- print(ret)
结果:
<generator object func at 0x10567ff68>
函数生成器的好处
return 方法的函数只能一次性拿取, 有时函数很大, 但只需求一部分时, 这种会很占内存;
但是 yield 方法的函数, 一次就拿一个, 用多少生成多少, 生成器是一次取一段, 节省内存, 但它不会回头.
如何使用函数生成器:
生成器本质还是迭代器, 所以我们可以直接执行__next__() 来执行函数生成器.
- def func():
- print("111")
- yield 222
- print("333")
- yield 444
- gener = func() #因为函数里是 yield 所以这个时候不是执行函数内容, 而是获取到生成器权限
- ret = gener.__next__() #执行函数内容, yield 也可返回数据. 但不会终止函数, 而是分段来执行一个函数
- print(ret)
- ret2 = gener.__next__()
- print(ret2)
- ret3 = gener.__next__() #只有两个 yield, 再来, 就会报错 StopIteration
- print(ret3)
send() 方法:
send 和__next__() 一样都可以让生成器执行到下一个 yield.
但 send() 和__next__还是又区别的:
1.send 和 next() 都是让生成器向下走一次
2.send 可以给上一个 yield 的位置传递值, 但不能给最后一个 yield 发送值, 在第一次执行生成器代码的时候不能使用 send()
生成器可以使用 for 循环来循环获取内部的元素:
- def func():
- print(111)
- yield 222
- print(333)
- yield 444
- print(555)
- yield 666
- gen = func()
- for i in gen:
- print(i)
结果:
111 222 333 444 555 666
三, 各种推导式.
列表推导式: 通过一行来构建你要的列表, 列表推导式代码简单, 但是出现错误后很难排查.
集合推导式: 可以帮我们直接生成一个集合, 并且可以去重
字典推导式: 可以帮我们生成一个字典, 例如需要将一个字典的 key 和 value 互换时用这个就很方便
但是就没有元组推导式.(估计是因为元组不可变的缘故)
列表推导式格式: [ 结果 for i in 可迭代对象 if 条件]
获取 1-100 内所有的偶数
- lst = [i for i in range(1, 100) if i % 2 == 0]
- print(lst)
四, 生成器表达式.
生成器表达式格式: (结果 for 变量 in 可迭代对象 if 条件筛选), 可以直接获取到生成器对象, 生成器对象可以直接进行 for 循环
- gen = (i for i in range(10))
- print(gen)
结果: <generator object <genexpr> at 0x106768f10>
打印的结果就是? 个生成器. 我们可以使用 for 循环来循环这个生成器:
- gen = ("麻花藤我第 %s 次爱你" % i for i in range(10))
- for i in gen:
- print(i)
生成器表达式也可以进行筛选:
寻找名字中带有两个 e 的? 的名字
- names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven','Joe'],
- ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
- gen = (name for first in names for name in first if name.count("e")>= 2)
- for name in gen:
- print(name)
生成器表达式和列表推导式的区别:
列表推导式比较耗内存. 一次性加载. 生成器表达式要下指令去拿值, 不下指令不会取值, 很节省内存
列表推导式得到的是? 个列表. 生成器表达式获取的是? 个生成器. 得到的值不一样
来源: http://www.bubuko.com/infodetail-2881331.html