logo

Python 迭代

王哲峰 / 2023-01-09


目录

for 循环包括多数计数器式的循环. 一般而言, forwhile 容易写, 执行时也比较快. 所以每当你需要遍历序列时, 都应该把它作为首选的工具.

但是, 有些情况下, 需要以更为特定的方式来进行迭代. 例如, 如果你需要在列表中每隔一个元素或每隔两个元素访问, 或者在过程中修改列表呢? 如果在同一个 for 循环内, 并行遍历一个以上的序列呢?

Python 提供了两个内置函数, 在 for 循环内定制迭代:

Python 可迭代对象

循环计数器: while 和 range

非完备遍历: range 和 分片

修改列表: range

并行遍历: zip & map

zip

zip 在 Python 3.0 中也是一个可迭代对象, 因此, 必须将其包含在一个 list 调用中以便一次性显示所有结果.

示例 1:

>>> L1 = [1, 2, 3, 4]
>>> L2 = [5, 6, 7, 8]
>>> zip(L1, L2)
>>> list(zip(L1, L2))

示例 2:

>>> for (x, y) in zip(L1, L2):
>>>     print(x, y, '--', x + y)

map

产生偏移和元素: enumerate

enumerate 函数返回一个生成器对象: 这种对象支持迭代协议, 这个对象有一个 __next__ 方法, 由下一个内置函数调用它, 并且循环中每次迭代的时候它会返回一个 (index, value) 的元组.

通过 range 来产生字符串中元素的偏移值, 而不是那些偏移值处的元素. 不过, 在有些程序中, 两者都需要:

从传统意义上来讲, 这是简单的 for 循环, 它同时持有一个记录当前偏移值的计数器.

# 普通的 for 循环
>>> S = "spam"
>>> offset = 0
>>> for item in S:
>>>     print(item, "appears at offset", offset)
>>>     offset += 1

# enumerate
>>> S = "spam"
>>> for (offset, item) in enumerate(S):
>>>     print(item, "appears at offset", offset)
>>> S = "spam"
>>> E = enumerate(S)
>>> E
>>> next(E)
>>> next(E)
>>> next(E)

>>> [c * i for (i, c) in enumerate(S)]

break, continue, pass, iter-else

文件扫描

Python 列表、字典解析、生成器

前提条件: 了解 Python 迭代协议

列表解析

列表解析基础知识

在 Python 中, 列表解析看上去就像一个反向的 for 循环, 下面分析一个例子

>>> L = [x + 10 for x in L]

其中:

在文件上使用列表解析

文件对象有个 readlines 方法, 它能一次性地把文件载入到行字符串的一个列表中:

with open("script1.py") as f:
    lines = f.readlines()
    lines = [line.rstrip() for line in lines]
lines = [line.rstrip() for line in open("script1.py")]

扩展的列表解析语法

lines = [line.rstrip() for line in open("script1.py") if line[0] == "p"]
[x + y for x in 'abc' for y in 'lmn']

列表解析与 map

增加测试和嵌套循环

列表解析和矩阵

理解列表解析

字典解析

生成器