Python 使用iter()函数,在纯粹的函数式语境中,递归函数处理所有可迭代对象,状态只存在于递归调用栈中。在实践中,Python的可迭代对象往往涉及对其他for
循环的求值。有两种常见的场景:集合和可迭代对象。当用于集合时,由for
语句创建迭代器对象;当用于生成器函数时,生成器函数本身就是迭代器,自己维护内部状态。在Python编程的大多数实践中,二者作用相同,但在某些特殊情况下,例如需要显式使用next()
函数时,二者的用法并不相同。
前面的legs()
函数使用了显式的next()
方法从可迭代对象中取值。对于可迭代对象,包括生成器函数和生成器表达式,使用这个函数完全没有问题,但对于序列对象,例如元组和列表,不能用这个函数。
下面3个例子说明了next()
函数和iter()
函数的作用:
>>> list(legs(x for x in range(3)))
[(0, 1), (1, 2)]
>>> list(legs([0,1,2]))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in legs
TypeError: 'list' object is not an iterator
>>> list(legs(iter([0,1,2])))
[(0, 1), (1, 2)]
第一个例子中,legs()
函数的参数是可迭代对象,也是生成器表达式,这种情况符合设计目标,数据正确组对,将三个位置点转换为两个路径段。
第二个例子尝试将序列用作legs()
函数的参数,结果发生了错误。虽然在for
语句中列表对象和可迭代对象的用法是一样的,但这并不适用于所有场景。序列不是迭代器,不能用作next()
函数的参数,for
语句为了处理这两类情形,自动基于序列创建了一个迭代器。
对于第二种情形,需要显式地基于列表对象创建一个迭代器,这样legs()
函数就可以通过迭代器获取列表中的第一个值了。iter()
函数负责将列表转换为迭代器。