【问题标题】:iter ,range in for loop pythoniter,范围在for循环python
【发布时间】:2018-12-20 01:02:10
【问题描述】:

我认为“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)) 时发生了什么?

【问题讨论】:

  • 迭代器是可迭代的

标签: python for-loop iterator generator


【解决方案1】:

迭代器也是可迭代的for 在它迭代的对象上调用 iter(),如果你已经有一个迭代器,那么它会产生对同一个对象的引用。这是设计使然。

来自iterator entry in the Python glossary

迭代器必须有一个返回迭代器对象本身的__iter__() 方法因此每个迭代器也是可迭代的,并且可以在接受其他迭代器的大多数地方使用。

我的粗体强调

来自同一个文档,术语iterable

使用iterables时,通常不需要调用iter()或者自己处理迭代器对象。 for 语句会自动为您执行此操作,创建一个临时的未命名变量来在循环期间保存迭代器。

来自Iterator types section of the standard types document

迭代器对象本身需要支持以下两种方法,它们共同构成了迭代器协议

iterator.__iter__()

返回迭代器对象本身。 这是允许容器和迭代器与forin 语句一起使用所必需的。

我的粗体强调

因此,当您使用for ... in iter(range(...)) 而不是for ... in range() 时,您对iter() 进行了额外的调用,这基本上是多余的,因为for 已经自己进行了调用。

但是你可以使用iter()之前你使用for循环来保持对迭代器的引用;所以你可以使用它来推进到下一个值其他地方,与for循环协调:

>>> 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()first,那么只有在for循环执行时才会出现异常,这会造成混淆,因为gen引用可能已经在代码中的任意位置创建,真的。

【讨论】:

  • 那为什么还要在超链接的生成器示例中使用 iter(range(10)) 呢?
  • @OpticalDataScience:因为 PEP 记录了生成器表达式实现的内部工作原理将在 调用生成器函数对象之前创建一个迭代器。实际实现不使用for 循环,它生成的字节码大致相当。
  • @OpticalDataScience:当您稍后在代码中使用该生成器表达式时,这很重要。如果 iter() 调用失败,它将在定义生成器表达式的位置失败,而不是在您最终迭代它的位置。
猜你喜欢
  • 1970-01-01
  • 2022-12-16
  • 2023-03-18
  • 1970-01-01
  • 2018-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多