我认为“ for in”语句采用可迭代对象而不是迭代器,但是以下代码可以正常工作。我很困惑。实际上,我在看发电机示例: https://www.python.org/dev/peps/pep-0289/
>>> for i in range(10):
print(i)
0
1
2
3
4
5
6
7
8
9
>>> for i in iter(range(10)):
print(i)
0
1
2
3
4
5
6
7
8
9
>>>
任何人都可以解释在for循环中使用iter(range(10))会发生什么情况吗?
答案 0 :(得分:2)
迭代器也是可迭代的。 for
在要迭代的对象上调用iter()
,如果您已经有一个迭代器,则生成对同一对象的引用。这是设计使然。
来自iterator
entry in the Python glossary:
迭代器必须具有
__iter__()
方法,该方法返回迭代器对象本身,因此每个迭代器也是可迭代的,并且可以在接受其他可迭代的大多数地方使用。
粗体强调我的。
在同一文档中,术语iterable
:
使用可迭代对象时,通常不必自己调用
iter()
或处理迭代器对象。for
语句会自动为您执行此操作,并创建一个临时的未命名变量来在循环过程中保留迭代器。
,并来自Iterator types section of the standard types document:
需要迭代器对象本身支持以下两种方法,它们共同构成了 iterator协议:
iterator.__iter__()
返回迭代器对象本身。 这是必需的,以允许容器和迭代器与
for
和in
语句一起使用。
粗体强调我的。
因此,当您使用for ... in iter(range(...))
而不是for ... in range()
时,您将对iter()
进行额外的通话,这基本上是多余的,因为for
已经进行了通话。
但是您可以在使用iter()
循环保留对迭代器的引用之前使用for
。因此您可以与for
循环配合使用它来前进到下一个值 elsewhere :
>>> range_iter = iter(range(10))
>>> for i in range_iter:
... print('for loop produced', i)
... if i % 4 == 0:
... j = next(range_iter)
... print('But we can advance the iterator manually, too:', j)
...
for loop produced 0
But we can advance the iterator manually, too: 1
for loop produced 2
for loop produced 3
for loop produced 4
But we can advance the iterator manually, too: 5
for loop produced 6
for loop produced 7
for loop produced 8
But we can advance the iterator manually, too: 9
在PEP中,detail section中的代码示例在调用生成器函数之前使用了iter()
调用 ,因为该iter()
调用可能提出一个例外。您希望在定义生成器表达式时引发该异常,而不是在以后尝试对生成器表达式进行迭代时引发该异常。
或者确切地说,以下代码在第一行失败,而不是在循环期间失败:
gen = (x ** 2 for x in 1) # 1 is not an iterable
for i in gen: print(i)
如果实现未先调用iter()
,则只有在执行for
循环时才会出现异常,这会造成混淆,因为{{1 }}确实可以在代码中的任意位置创建引用。