DAY 6. 生成式,迭代器,生成器
6.1 生成式
6.1.1 列表生成式
list = [index for index in range(10)]
6.1.2 字典生成式
dict = {'zhangsan': 10,'lisi': 12,'wangwu': 18
}
# 实现键值互换
dict = {k:v for v,k in dict.items() if k >= 12}
6.1.3 集合生成式
# 100以内的质数
set = {i for i in range(100) if i % 2 != 0}
6.2 生成器
生成式会创建一个列表(字典或集合),但无论是字典,列表还是集合,都不能保存一个无限长的序列,比如说全体自然数,当然我们一般不会用到这种序列,但哪怕是万位的序列,保存为列表或集合也是很占用空间的,加上一般情况下我们对一个序列的操作是一次性的,根本不需要保存,那有没有一种办法只有我们需要时才给我们数据,我们不需要时程序只保留“算法”呢?这就用到了生成器
创建生成器有两种办法,一种是类似于推导式,把列表推导式的中括号改为小括号就行,会返回一个生成器对象,可以使用next()或for循环遍历
t = (i for i in range(100) if i % 2 == 0)
for i in t:print(i)
举个栗子,斐波那契数列,每一项是前两项之和
一般情况
feibo = [1, 1]
for i in range(2,10000):feibo.append(feibo[i - 1] + feibo[i - 2])
print(feibo)
我们要做的只是要打印出来而已,没必要保存这么大的数组,这时我们可以用生成器
def feb(f, s, max):i = 0while i < max:f, s = s, f + si += 1yield sfor i in feb(1, 1, 100):print(i)
生成器长得和函数一样,只不过return 变成了yield ,每当运行到yield后,程序就会阻塞,只有在调用该生成器的next()方法时才会从上次暂停的地方继续
def Demo():print(1)yield 1print(2)yield 2print(3)yield 3demo = Demo()
next(demo)
next(demo)
next(demo)
next(demo)# 1
# 2
# 3
# Traceback (most recent call last):
# File "E:/xxxx/DAY6_1.py", line 45, in <module>
# next(demo)
# StopIteration
当超出生成器范围时会抛出StopIteration异常,我们一般也不会使用next,for就是捕捉StopIteration异常遍历生成器的
for i in Demo():i# 等价于while(True):try:next(demo)except StopIteration:break
6.3 迭代器
6.3.1 可迭代对象
可以直接作用于for循环的对象统称为可迭代对象:Iterable,主要有两类,列表,元组,字典,集合等数据类型和生成器,可以使用isinstance()判断一个对象是否是Iterable对象。
6.3.2 迭代器
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。可以使用isinstance()判断一个对象是否是Iterator对象
生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。把list、dict、str等Iterable变成Iterator可以使用iter()函数
你可能会问,为什么list、dict、str等数据类型不是Iterator?
这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。
Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。
6.4 总结
- 生成式
生成式 | 语法 |
---|---|
列表生成式 | L = [i for i in range(100) if i % 2 ==0] |
字典生成式 | k:v for k, v in dict.items() if k < 10 |
集合生成式 | S = {i for i in range(100) if i % 2 ==0} |
- 生成器
创建:
生成式方式和生成器函数
读取:
next()或for
- 迭代器
可迭代对象 | 能被for直接作用的对象 |
---|---|
迭代器 | 能用next()执行的可迭代对象 |
参考文章:
GitHub python面试题
廖雪峰的官方网站
python 生成器和迭代器有这篇就够了