生成器的Python循环行为

skr*_*sme 2 python loops yield return generator

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

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
Run Code Online (Sandbox Code Playgroud)

此代码的输出是:

对于计数:0
对于计数:1
对于计数:2
对于计数:3
对于计数:4
虽然计数:0
但计数:1
计数:2
计数:3
计数:4
计数:5计数:5
计数:6
计数:7
虽然数:8
虽然数:9
虽然数:10

我很感激帮助理解以下内容:

  1. for循环如何知道何时结束但不知道第二个while循环?我希望两个while循环都能立即退出,因为它None已经产生了.
  2. 为什么不使用.next()引发异常?该consumer程序是不是有一个类__next__()定义的方法,所以它奇迹般地当您使用出现yield的关键字?
  3. 为什么,如果我更改consumer到yield item,第一while循环变得无限大,如第二个?
  4. 如果我consumer改为简单地返回而不是产生任何东西,则第二个while循环立即退出而不是变为无限.我一直认为a yield本质上是return你可以从中恢复的.为什么while循环处理不同?

Ada*_*tan 6

该for环

您的第一个for循环按预期工作. 更新:Mark Ransom注意到你yield没有预期的item,所以它只是返回[None, None, None, None, None]而不是[1, 2, 3, 4, 5]- 但它仍然在列表中迭代.

第一个while循环

同样的评论员也注意到第一个while循环永远不会启动,因为0它False在Python中是等价的.

第二个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
Run Code Online (Sandbox Code Playgroud)

赠送:

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>
Run Code Online (Sandbox Code Playgroud)

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