生成器的 Python 循环行为

标签 python loops return generator yield

我很困惑为什么不同的循环结构在与简单生成器一起使用时表现如此不同。考虑以下代码:

example_list = [1, 2, 3, 4, 5]
for_count = 0
next_count = 0
while_count = 0

def consumer(iterable):
    for item in iterable:
        yield    
    return

for item in consumer(example_list):
    print("For Count: {0}".format(for_count))
    for_count += 1

# First while loop
while consumer(example_list).next():
    print("Next Count: {0}".format(next_count))
    next_count += 1

# Second while loop
while consumer(example_list):
    print("While Count: {0}".format(while_count))
    while_count += 1
    if while_count > 10: # add contrived limit for infinite loop
        break

这段代码的输出是:

For Count: 0
For Count: 1
For Count: 2
For Count: 3
For Count: 4
While Count: 0
While Count: 1
While Count: 2
While Count: 3
While Count: 4
While Count: 5
While Count: 6
While Count: 7
While Count: 8
While Count: 9
While Count: 10

如果能帮助您理解以下内容,我将不胜感激:

  1. for 循环如何知道何时结束而不是第二个 while 循环?我预计 while 循环会立即退出,因为生成了 None
  2. 为什么不使用 .next() 引发异常? consumer 例程不是定义了 __next__() 方法的类,所以当您使用 yield 关键字时它会神奇地出现吗?
  3. 为什么如果我将 consumer 更改为 yield item,第一个 while 循环会像第二个一样变成无限循环?
  4. 如果我将 consumer 更改为简单地 return 而不是产生任何东西,第二个 while 循环会立即退出而不是变成无限循环。我一直认为 yield 本质上是一个 return,您可以从中恢复。为什么 while 循环会区别对待它们?

最佳答案

for 循环

您的第一个 for 循环按预期工作。 更新:Mark Ransom请注意,您的 yield 没有附带预期的 item,因此它只返回 [None, None, None, None, None] 而不是[1, 2, 3, 4, 5] - 但它仍然遍历列表。

第一个while循环

The very same commentator还注意到第一个 while 循环永远不会开始,因为 0 在 Python 中是一个 False 等价物。

第二个while循环

在第二个 while 循环中,您正在测试 consumer(example_list) 的值。这是生成器对象本身,而不是其 next() 返回的值。对象本身永远不会等于 None 或任何其他 False 等价物 - 因此您的循环永远不会结束。

这可以通过在循环内打印 consumer(example_list) 的值(您的 while 条件)看出:

>>> while_count=0
>>> while consumer(example_list):
...     print while_count, consumer(example_list)
...     while_count += 1
...     if while_count > 10:
...         break

给予:

0 <generator object consumer at 0x1044a1b90>
1 <generator object consumer at 0x1044a1b90>
2 <generator object consumer at 0x1044a1b90>
3 <generator object consumer at 0x1044a1b90>
4 <generator object consumer at 0x1044a1b90>
5 <generator object consumer at 0x1044a1b90>
6 <generator object consumer at 0x1044a1b90>
7 <generator object consumer at 0x1044a1b90>
8 <generator object consumer at 0x1044a1b90>
9 <generator object consumer at 0x1044a1b90>
10 <generator object consumer at 0x1044a1b90>

第二项是对象,永远不会等于None

关于生成器的 Python 循环行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25534862/

相关文章:

python - 从 stdin 读取,同时消耗的内存不超过需要

list - 从列表中循环 flextable 不会在 Word 中创建表格

c - 在循环中使用int n = strlen(…)时出现运行时错误

java - 无法从嵌套的 for 循环返回字符串

java - 从 .txt 文件中读取方程式并将其设置为方法的返回

javascript - 返回函数内的组件不起作用

python - 使用 pandas 从 CSV 加载随机样本

python - PyQt4 拖放

python - 使用 python 2.7,为什么我的 unicode 文件名在调用 file() 时会引发 IOError ?

javascript - Javascript:由用户输入分配变量时崩溃