>>> from env_helper import info; info()
页面更新时间: 2023-07-01 15:18:23
运行环境:
    Linux发行版本: Debian GNU/Linux 12 (bookworm)
    操作系统内核: Linux-6.1.0-9-amd64-x86_64-with-glibc2.36
    Python版本: 3.11.2

11.2. 迭代器

迭代器是一个表示数据流的对象;这个对象每次只返回一个元素。 迭代器的一个优点就是它不要求你事先准备好整个迭代过程中所有的元素。 迭代器仅仅在迭代至某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。 这个特点使得它特别适合用于遍历一些巨大的或是“无限”的集合。

11.2.1. 迭代器的使用

内置的 iter() 函数接受任意对象并试图返回一个迭代器来输出对象的内容或元素,并会在对象不支持迭代的时候抛出 TypeError 异常。 Python 有几种内置数据类型支持迭代,最常见的就是列表和字典。如果一个对象能生成迭代器,那么它就会被称作 iterable。

11.2.2. 获取迭代器对象

迭代器是一个使用率较高的工具,Python 有不少要求使用可迭代的对象的地方, 其中最重要的就是 for 表达式。 在表达式 for X in YY 要么自身是一个迭代器,要么能够由 iter() 创建一个迭代器。

以下两种:

>>> lst = range(2)
>>>
>>> lst
range(0, 2)
>>> lit = iter(lst)
>>> lit
<range_iterator at 0x7f78b43ddfe0>

使用迭代器的 next() 方法可以访问下一个元素,如果超出了范围就会返回一个 StopIteration 异常, 事实上Python正是利用一些异常来控制流程的进行。 在 for 循环中,Python将自动调用工厂函数 iter() 获得迭代器,自动调用 next() 获取元素,还完成了检查 StopIteration 异常的工作。

>>> next(lit)
0
>>> next(lit)
1

还可以利用 list()tuple() 这样的函数把迭代器具体化成列表或元组。 要注意,在程序中迭代器随时发生着变化 ,转换的结果与迭代器中迭代的位置有关系。

>>> lit = iter(lst)
>>> next(lit)
>>> t = tuple(lit)
>>> t
(1,)

序列的解压操作也支持迭代器:如果你知道一个迭代器能够返回 N 个元素,你可以把他们解压到有 N 个元素的元组:

>>> L = [1, 2, 3]
>>> iterator = iter(L)
>>> a, b, c = iterator
>>> a, b, c
(1, 2, 3)

max()min() 这样的内置函数可以接受单个迭代器参数,然后返回其中最大或者最小的元素。 innot in 操作也支持迭代器:如果能够在迭代器 iterator 返回的数据流中找到 X 的话,则 X in iterator 为真。 很显然,如果迭代器是无限的,这么做你就会遇到问题; max()min() 永远也不会返回;如果元素 X 也不出现在数据流中,innot in 操作同样也永远不会返回。

11.2.3. 使用迭代器的数据类型

常用的几个内建数据结构 tuple、list、set、字典都支持迭代器,字符串也可以使用迭代操作, 对字典调用 iter() 会返回一个遍历字典的键的迭代器:

>>> info={"name":"Bob","age":18,"ID":123}
>>> for key in info:
>>>     print(key, info[key])
name Bob
age 18
ID 123

dict() 构造函数可以接受一个迭代器,然后返回一个有限的 (key, value) 元组的数据流:

>>> info1=[("name","Bob"),("age",18),("ID",123)]
>>> dict(iter(info1))
{'name': 'Bob', 'age': 18, 'ID': 123}

文件也可以通过调用 readline() 来遍历,直到穷尽文件中所有的行。这意味着你可以像这样读取文件中的每一行:

>>> filei = open('chapter.ipynb')
>>> filei.readline()
'{n'
>>> filei.readline()
' "cells": [n'
>>> filei.readline()
'  {n'

11.2.4. 列表推导式和生成器表达式

掌握了迭代器的使用后,就要继续讲到函数式编程的另一个工具,生成器。 迭代器的输出有两个很常见的使用方式:

  1. 对每一个元素执行操作,

  2. 选择一个符合条件的元素子集,

列表推导式和生成器表达让这些操作更加简明,绝大多数情况下,遍历一个集合都是为了对元素应用某个动作或是进行筛选。

通过列表推导式,你会获得一个 Python 列表。 列表解析,返回list :

>>> [x+1 for x in lst]
[1, 2]

通过生成器表达式,你会获得一个迭代器。

>>> (x+1 for x in lst)
<generator object <genexpr> at 0x7fa48c13edc0>

生成器表达式会返回一个迭代器,它在必要的时候计算结果,避免一次性生成所有的值。 这意味着,如果迭代器返回一个无限数据流或者大量的数据,列表推导式就不太好用了。 这种情况下生成器表达式会更受青睐。

11.2.5. any() 函数

any() 函数用于判断给定的可迭代参数 iterable 是否全部为 False ,则返回 False ,如果有一个为 True ,则返回 True

元素除了是 0NoneFALSE 外都算 TRUE

函数等价于:

def any(iterable):
    for element in iterable:
        if element:
            return True
    return False

Python 2.5 以上版本可用。

以下是 any() 方法的语法:

any(iterable)

参数: iterable – 元组或列表。 返回值: 如果都为空、0、false,则返回false,如果不都为空、0、false,则返回true。

以下展示了使用 any() 方法的实例:

列表list,元素都不为空或0

>>> any(['a', 'b', 'c', 'd'])
True

列表list,存在一个为空的元素

>>> any(['a', 'b', '', 'd'])
True

列表list,元素全为0,’’,false

>>> any([0, '', False])
False

空列表

>>> any([])
False

空元组

>>> any(())
False