lambda 本身不会迭代任何东西。正如你所想,它只是定义了一个匿名函数——除了只能有一个表达式的语法规则之外,lambda 只不过是使用def 制作的类似函数。 lambda 中的代码可能会迭代某些内容,但只能以与任何其他函数可能使用的方式相同的方式(前提是它们是表达式,并且在 lambda 中有效)。
在您提到的使用sorted 的示例中,对要排序的列表的每个元素调用键函数-但sorted 本身执行此操作,并执行迭代。当您提供一个关键功能时,sorted 会做一些与此大体相似的事情:
def sorted(seq, key):
decorated = [(key(elem), i) for i, elem in enumerate(seq)]
# Sort using the normal tuple lexicographic comparisons
decorated.sort()
return [seq[i] for _,i in decorated]
如您所见,sorted 在此处进行迭代,而不是 lambda。事实上,没有理由将键 设为 lambda - 就sorted 而言,任何函数(或任何可调用函数)都可以。
在最低级别,只有一种方法可以在 Python 中迭代 dict(或者实际上是任何其他可迭代对象),即使用 iterator 协议。这就是 for 循环在幕后所做的事情,您也可以像这样使用 while 语句:
it = iter(my_iterable)
while True:
try:
val = next(it)
except StopIteration:
# Run else clause of for loop
break
else:
# Run for loop body
这里的 cmets 并不是严格意义上的迭代器协议的一部分,它们是 for 循环的一部分(但其中至少有一个循环体,这首先是迭代的重点)。
其他使用可迭代对象的函数和语法(例如列表、集合和字典推导、生成器表达式或像 sum、sorted 或 sorted 或 max 这样的内置函数)都使用此协议,通过以下任一方式:
- 使用 Python
for 循环,
- 执行类似于上述
while 循环的操作(尤其是对于用C 编写的模块),
- 委托给另一个函数或使用其中之一的语法片段
可以创建一个类,使其实例变为可通过以下两种方式之一进行迭代:
- 直接提供迭代器协议。您需要一个名为
__iter__(由iter 调用)的方法,该方法返回一个迭代器。该迭代器有一个名为 __next__ 的方法(在 Python 2 中只是 next),该方法由 next 调用并返回迭代器当前位置的值并推进它(如果它已经在末尾,则引发 StopIteration );或
- 实现部分序列协议(这意味着表现得像一个列表或元组)。对于前向迭代,以这样的方式定义
__getitem__ 就足够了:执行my_sequence[0]、my_sequence[1],直到my_sequence[n-1](其中n 是序列中的项目数),并且更高的索引会提高一个错误。你通常也想定义__len__,当你做len(my_sequence)时使用它。