第14章 迭代器和解析,第一部分
写在开头的读者笔记
值得一读的小节
1.迭代器:初探
1.1.迭代器:初探 - 文件迭代器
迭代协议:有__next__
方法的对象会前进到下一个结果,而在一系列结果的末尾时,则会引发StopIteration。在Python中,任何这类对象都认为是可迭代的(iterable)。任何这类对象也能以for循环或其他迭代工具遍历,因为所有迭代工具内部工作起来都是在每次迭代中调用__next__
,并且捕捉StopIteration异常来确定何时离开。
迭代器for循环的版本,在Python中是以C语言的速度运行的,而while循环版本则是通过Python虚拟机运行Python字节码的,可能运行得更慢一些。
1.2.迭代器:初探 - 手动迭代:iter和next
Python3.0提供了内置函数next,它会自动调用一个对象的__next__
方法。给定一个可迭代对象 X,调用next(X)等同于X.__next__()
。
>>> f = open('script1.py')
>>> f.__next__()
'import sys\n'
>>> f.__next__()
'print(sys.path)\n'
>>> f.__next__()
'x = 2\n'
>>> f.__next__()
'print(2 ** 33)'
>>> f.__next__()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> f = open('script1.py')
>>> next(f)
'import sys\n'
>>> next(f)
'print(sys.path)\n'
>>> next(f)
'x = 2\n'
>>> next(f)
'print(2 ** 33)'
迭代协议还有一点值得注意。当for循环开始时,会通过它传给iter内置函数,以便从可迭代对象中获得一个迭代器,返回的对象含有需要的next方法。for循环内部如何处理列表这类内置序列类型的:
$ python2
Python 2.7.12 (default, Nov 19 2016, 06:48:10)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> L = [1,2,3]
>>> I = iter(L)
>>> I.next()
1
>>> I.next()
2
>>> I.next()
3
>>> I.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
最初的一步(应该是指调用iter方法)对于文件来说不是必需的,因为文件对象就是自己的迭代器。也就是说,文件有自己的__next__
方法,因此不需要想这样返回一个不同的对象:
$ python3
Python 3.5.2 (default, Nov 17 2016, 17:05:23)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> f = open('script1.py')
>>> iter(f) is f
True
>>> f.__next__()
'import sys\n'
列表以及很多其他的内置对象,不是自身的迭代器,因为它们支持多次打开迭代器。对这样的对象,我们必须调用iter来启动迭代:
$ python3
Python 3.5.2 (default, Nov 17 2016, 17:05:23)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> L = [1,2,3]
>>> iter(L) is L
False
>>> L.__next__()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute '__next__'
>>> I = iter(L)
>>> I.__next__()
1
>>> next(I)
2
2.Python 3.0中的新的可迭代对象
2.1.Python 3.0中的新的可迭代对象 - range迭代器
在Python3.0中,range函数返回一个迭代器,该迭代器根据需要产生范围中的数字,而不是在内存中构建一个结果列表。
>>> r = range(10)
>>> r
range(0, 10)
>>> list(r)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
迭代器:初探
文件迭代器
(读者:
迭代协议:有__next__
方法的对象会前进到下一个结果,而在一系列结果的末尾时,则会引发StopIteration。在Python中,任何这类对象都认为是可迭代的(iterable)。任何这类对象也能以for循环或其他迭代工具遍历,因为所有迭代工具内部工作起来都是在每次迭代中调用__next__
,并且捕捉StopIteration异常来确定何时离开。
迭代器for循环的版本,在Python中是以C语言的速度运行的,而while循环版本则是通过Python虚拟机运行Python字节码的,可能运行得更慢一些。
)
手动迭代:iter和next
(读者:Python3.0提供了内置函数next,它会自动调用一个对象的__next__
方法。给定一个可迭代对象 X,调用next(X)等同于X.__next__()
。
>>> f = open('script1.py')
>>> f.__next__()
'import sys\n'
>>> f.__next__()
'print(sys.path)\n'
>>> f.__next__()
'x = 2\n'
>>> f.__next__()
'print(2 ** 33)'
>>> f.__next__()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> f = open('script1.py')
>>> next(f)
'import sys\n'
>>> next(f)
'print(sys.path)\n'
>>> next(f)
'x = 2\n'
>>> next(f)
'print(2 ** 33)'
迭代协议还有一点值得注意。当for循环开始时,会通过它传给iter内置函数,以便从可迭代对象中获得一个迭代器,返回的对象含有需要的next方法。for循环内部如何处理列表这类内置序列类型的:
$ python2
Python 2.7.12 (default, Nov 19 2016, 06:48:10)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> L = [1,2,3]
>>> I = iter(L)
>>> I.next()
1
>>> I.next()
2
>>> I.next()
3
>>> I.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
最初的一步(应该是指调用iter方法)对于文件来说不是必需的,因为文件对象就是自己的迭代器。也就是说,文件有自己的__next__
方法,因此不需要想这样返回一个不同的对象:
$ python3
Python 3.5.2 (default, Nov 17 2016, 17:05:23)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> f = open('script1.py')
>>> iter(f) is f
True
>>> f.__next__()
'import sys\n'
列表以及很多其他的内置对象,不是自身的迭代器,因为它们支持多次打开迭代器。对这样的对象,我们必须调用iter来启动迭代:
$ python3
Python 3.5.2 (default, Nov 17 2016, 17:05:23)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> L = [1,2,3]
>>> iter(L) is L
False
>>> L.__next__()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute '__next__'
>>> I = iter(L)
>>> I.__next__()
1
>>> next(I)
2
)
其他内置类型迭代器
列表解析:初探
列表解析基础知识
在文件上使用列表解析
扩展的列表解析语法
其他迭代环境
Python 3.0中的新的可迭代对象
range迭代器
(读者:在Python3.0中,range函数返回一个迭代器,该迭代器根据需要产生范围中的数字,而不是在内存中构建一个结果列表。
>>> r = range(10)
>>> r
range(0, 10)
>>> list(r)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
)
map、zip和filter迭代器
字典视图迭代器
其他迭代器主题
本章小结
习题解答
参考文献:
1.《Python学习手册》。