形式上,Python 中的for statement 总是在iterable 上运行——一个可以在其项目上提供iterator 的对象。 for 语句连续获取 next element from the iterator,将其分配给目标名称并使用它运行套件(“body”)。
# |name| |iterable|
for party in feed.entry:
# body...
print(party.location.address.text)
在示例中,feed.entry 是可迭代对象,party 是目标名称,print ... 是套件。迭代器由for 语句自动请求,并保持迭代状态 - 例如如果可迭代是列表,则为下一个元素的索引。
如果您来自 C++,经典的 for (int i = 0; i < 10; ++i) loop 代表 external iteration:迭代状态 i 保留在可迭代对象之外。这对应于 Python 的 while 循环:
# for (int i = 0; i < 10; ++i)
i = 0
while i < 10:
i += 1
# access the state of an iterable here
较新的for (auto party : entry) range loop 表示内部迭代:迭代状态由单独的迭代器保存。这对应于 Python 的 for 循环。然而,iterable/iterator 协议明显不同:Python 的 for 使用 iter(iterable) 获取迭代器,它应该支持 next(iterator) - 返回一个元素或引发 StopIteration。
用 Python 编写,definition of the for statement 对应如下:
# for party in feed.entry:
__iterator = iter(feed.entry) # iterator -- not visible in containing scope
__iterating = True # graceful exit to enter `else` clause
while __iterating:
try: # attempt to...
item = next(__iterator) # ... get the next item
except StopIteration: # ... or stop
__iterating = False # with a graceful exit
else:
party = item
<suite> # run the body with names bound
else: # entered in a graceful exit only
<else suite>
(请注意,从__iterating = True 到__iterating = False 的整个块对包含范围来说是不“可见的”。实现使用各种优化,例如CPython 允许builtin iterators to return a C NULL instead of raising a Python StopIteration。)
for 语句只是定义了 如何 使用迭代器和迭代器。如果您最熟悉外部迭代,那么查看可迭代和迭代器也会有所帮助。
iter(iterable) 调用具有 multiple ways to derive an iterator - 这就像 iter 为各种结构类型重载。
无论哪种方式,iter 都会返回 iterator 或引发 TypeError。迭代器是 any 类型,它定义了__iter__(用于可重用性)和__next__(用于实际迭代)。通常,迭代器是可以保存状态以计算__next__ 项的对象。例如,一个列表迭代器对应这个对象:
class ListIterator:
"""Python equivalent of ``iter(:list)``"""
# iterator holds iteration state - e.g. iterable and current index
def __init__(self, iterable: list):
self.iterable = iterable
self.index = 0
# __next__ fetches item and advances iteration state - e.g. index += 1
def __next__(self):
# attempt to produce an item
try:
item = self.iterable[self.index]
except IndexError: # translate indexing protocol to iteration protocol
raise StopIteration
# update iteration state
self.index += 1
return item
# iterators can be iterated on in ``for`` statements etc.
def __iter__(self):
return self
(请注意,人们习惯性地将这样的对象写成generator function。)
索引列表或增加一些指针只是可迭代/迭代器协议的一个非常基本的例子。例如,迭代器可以是无状态的,并在__next__ 中使用random.random() 来产生无限的随机数流。例如,迭代器还可以保存外部信息的状态,并迭代地遍历文件系统。