1. 主要内容
- 迭代器
- 生成器
2. 迭代器
- 可迭代协议:
- 只要含有双下划线iter方法的都是可迭代的
- 可以被for循环的都是可迭代的,for循环其实就是在使用迭代器
- 迭代器协议:
- 内部含有__iter__和__next__方法的就是迭代器
- 只要是迭代器,就一定可以迭代
- 可迭代的.__iter__()方法就可以得到一个迭代器
- 迭代器中的.__next__()方法可以一个一个的获取值
- 惰性运算
- 迭代器的好处
- 从容器类型中一个一个的获取值
- 节省内存空间(需要时才会执行,每次__next__()生成一个值)
- 判断可迭代和迭代器的一种方法
1 | from collections import Iterable |
3. 生成器
- 生成器的本质:迭代器
- 生成器的表现形式:
- 生成器函数
- 生成器表达式
- 生成器函数:
- 只要含有yield关键字的函数都是生成器函数
- yield不能和return共用,且需要写在函数内部
- 调用生成器函数会得到一个生成器
- 生成器运行方式:
- 通过__next__执行
- 通过for循环执行
- 数据类型强制转换
- 通过send执行
1 | def generator(): |
- send的使用方法:
- 利用send执行的过程中,可以给上一个yield的地方传值
- 第一次使用生成器的时候,利用next获取下一个值
- 最后一个yield不能接收外部的值
1 | def generator(): |
- 生成器表达式:
列表推导式—返回列表
1
2
3
4
5
6
7
8
9
10egg_list = ['egg%s' % (i*i) for i in range(10)]
print(egg_list)
ret = [i*i for i in range(30) if i%3 == 0]
print(ret)
#根据条件筛选查找嵌套列表并返回
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
ret = [j for i in names for j in i if j.count('e') == 2]
print(ret)字典推导式
1
2
3
4
5
6
7
8#字典key,value对调
mcase = {'a': 10, 'b': 34}
ret = {mcase[i]:i for i in mcase.keys()}
print(ret)
# 例二:合并大小写对应的value值,将k统一成小写
mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
ret = {k.lower():(mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0))for k in mcase.keys()}
print(ret)集合推导式
1
2
3# 计算列表中每个值的平方,自带去重功能
squared = {x**2 for x in [1, -1, 2]}
print(squared)生成器表达式—返回生成器
1
2
3g = ('egg%s' % (i*i) for i in range(10))
for i in g:
print(i)
4. 例题
- 利用生成器监听文件输入
利用生成器的yield特性,不需要一次返回所有的值,只是将功能提供给用户,用户需要时进行循环输出或选择性输出。1
2
3
4
5
6
7
8
9
10
11def tail(filename):
f = open(filename,encoding='utf-8')
while True:
line = f.readline()
if line.strip():
yield line.strip()
g = tail('file')
for i in g:
if 'python' in i:
print('***',i)
- 获取移动平均值
- 利用yield和send配合
- 第一步的生成器__next__初始化通过装饰器来预激活
1 | def init(func): |

4. 练习题
1 | # 练习题: |