目录
- 1、可迭代对象和 for 语句
- 2、上下文管理器和 with 语句
1. 总结
1.1 概念区分
可得迭代对象、迭代器和生成器?
一句话:迭代器和生成器都属于可迭代对象,含有__iter__和__next__魔法函数的对象都是迭代器(可以为你的类添加迭代器),生成器是一种快速创建迭代器的方法。
迭代器(Iterator)
-
可以被next()函数调用并不断返回下一个值的对象称为迭代器(Iterator)。迭代器(iterator)是惰性可迭代对象(lazy iterable),是一次性可迭代对象。
可以使用isinstance()判断一个对象是否是Iterator对象。
生成器:特殊迭代器
- 生成器(来自于生成器函数或者生成器表达式)其实是一种特殊的迭代器
可迭代对象( Iterable)
-
可以直接作用于for循环的对象统称为可迭代对象(Iterable)。包括两类数据类型:
一类是容器数据类型,如list、tuple、dict、set、str等;
一类是生成器,包括生成器表达式和带yield的生成器函数。可以使用isinstance()判断一个对象是否是Iterable对象。
注意:list、dict、str虽然是Iterable,却不是Iterator。(因为Python的Iterator对象表示的是一个数据流)
把list、dict、str等Iterable变成Iterator可以使用iter()函数。
1.2 本质
- 迭代器是包含__next__方法的对象。(__next__方法可以记住遍历的位置)
- 可迭代的对象是可直接用于遍历的对象,包含__iter__方法。Iterable的__iter__方法会返回一个Iterator(iter()函数会返回一个定义了next()方法的迭代器对象)
2. 迭代器:惰性可迭代对象
记住:迭代器的存在是为了管理 for 语句
迭代(Iteration)是访问集合元素(collection)的一种方式。迭代器(Iterator )是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
注意:
1.在迭代器对象上调用 iter() 函数时,总会返回相同的对象
2.迭代器对象一定可以使用 next() 函数
3.迭代器对象只能被遍历一次
特殊的惰性迭代对象:range()
偶然发现一个有意思的事情:type(range)
的结果是type
,type(range(3))
的结果是range
,不禁思考 type 同 object 的关系,以及***range 代表的是什么类型***。
具体可以参考 Python 核心知识 0 ——框架&总章 中的Python基础知识。
range()函数是一个可得迭代对象(其本身不是迭代器),它本身可以返回一个迭代器(可以调用next函数),而不是一个列表类型。
- 语法
range(stop)
range(start, stop[, step])
返回的是一个可迭代对象:步数为step、从start 到 stop-1 的整数序列。
- 用法
① 与 for 循环一起使用;
② 使用 list() 函数转换为列表(可以打印出来)
- 例子
range(3) # 返回的是一个迭代器
range(0, 3)
for i in range(3):
print(i)
0
1
2
list(range(3))
[0, 1, 2]
返回迭代器的内置函数
注意上面图片上的错误:range()比较特殊,并不是返回一个迭代器,而只是返回一个可迭代对象。
下面就是一些能够返回迭代器的 Python 内置函数:
enumerate()
- 语法
enumerate(sequence, [start=0])
输入一个序列,返回 enumerate(枚举) 对象。
-
用法
① 与 for 循环一起使用;
② 使用 list() 函数转换为列表(可以打印出来) -
例子
enumerate(range(4, 7))
<enumerate at 0x1126a9948>
for n, i in enumerate(range(4, 7)) :
print(n, i)
0 4
1 5
2 6
list(enumerate(range(3)))
[(0, 0), (1, 1), (2, 2)]
reversed()
-
语法
reversed(seq)
返回一个反转的迭代器。 -
例子
reversed(range(3))
<range_iterator at 0x1131485a0>
for i in reversed(range(3)):
print(i)
2
1
0
list(reversed(range(3)))
[2, 1, 0]
zip()
- 语法
zip(iter1 [,iter2 […]])
返回一个 zip 对象,其.next()方法会返回一个元组。
- 例子
zip(range(3), range(3,6))
<zip at 0x112a974c8>
list(zip(range(3), range(3,6)))
[(0, 3), (1, 4), (2, 5)]
sorted()
- 语法
sorted(iterable, key=None, reverse=False)
返回可迭代对象重新排序的列表。
- 例子
sorted((3,7,1,0,5))
[0, 1, 3, 5, 7]
注意:区分list的方法 list.sort()
附:
Python 内置函数数量没有想的那么多,可以顺带多学习学习:Python3 内置函数
3. 生成器
定义生成器的两种方法:生成器表达式和生成器函数
- 生成器表达式。生成器表达式是列表推倒式的生成器版本,看起来像列表推导式,但是它返回的是一个生成器对象而不是列表对象。只要把一个列表生成式的[]改成(),就创建了一个generator。
- 如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator。
4. 上下文管理器和 with 语句
4.1 概述
含有 __enter__
和 __exit__
方法的对象就是 Python 的上下文管理器(Context Managers)。
上下文管理器存在的目的是管理 with 语句,就像是迭代器的存在是为了管理 for 语句一样。
with 上下文管理器:
语句体
当 with 遇到上下文管理器,就会在执行语句体之前,先执行上下文管理器的 enter 方法,然后再执行语句体,执行完语句体后,最后执行 exit 方法。
with
有一个很重要的作用是简化 try/finally 模式
,无论何种异常发生,finally 字句都会执行。
4.2 实例
- 有问题的代码
file = open("1.txt")
data = file.read()
file.close()
问题:可能出现 ①文件读取发生异常但没有进行任何处理 ② 肯能忘记关闭文件句柄
- 改进代码
try:
f = open('xxx')
except:
print('fail to open')
exit(-1)
try:
do something
except:
do something
finally:
f.close()
虽然这段代码运行良好,但比较冗长。
- with 语句
使用with的话,能够减少冗长,还能自动处理上下文环境产生的异常
with open('1.txt') as file:
data = file.read()
参考:
文件的打开、读写和关闭:
- 文件打开后才能进行读写
- Python会缓存写入的数据,如果程序异常崩溃,数据就不能写入到文件当中。安全起见,文件用完后要主动关闭文件