关于generator:Python中的yield break

yield break in Python

根据这个问题的答案,C中的yield break相当于python中的return。在正常情况下,"返回"确实会停止发电机。但是如果您的函数除了返回什么都不做,您将得到一个none-not-empty迭代器,该迭代器由C中的yield break返回。#

1
2
3
4
5
def generate_nothing():
    return

for i in generate_nothing():
    print i

您将得到一个类型错误:"nonetype"对象不可重复。但如果在返回之前添加一个从不运行的yield,这个函数将返回我所期望的。

1
2
3
def generate_nothing():
    if False: yield None
    return

如果可以,但似乎是有线的。谁有更好的主意?

谢谢,


1
2
3
def generate_nothing():
    return
    yield


处理这一问题的一个好方法是引发stopIteration,当迭代器没有剩余内容可生成并且调用next()时,就会引发stopIteration。这也将优雅地从for循环中断,循环中没有执行任何操作。

例如,给定一个元组(0, 1, 2, 3),我想得到重叠对((0, 1), (1, 2), (2, 3))。我可以这样做:

1
2
3
4
5
6
def pairs(numbers):
    if len(numbers) < 2:
        raise StopIteration

    for i, number in enumerate(numbers[1:]):
        yield numbers[i], number

现在,pairs可以安全地处理1个或更少的列表。


1
2
def generate_nothing():
    return iter([])


有趣的是两个函数都有相同的字节码。当字节码编译器找到yield关键字时,可能有一个标志设置为generator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>> def f():
...   return

>>> def g():
...   if False: yield
#in Python2 you can use 0 instead of False to achieve the same result


>>> from dis import dis
>>> dis(f)
2           0 LOAD_CONST               0 (None)
            3 RETURN_VALUE
>>> dis(g)
2           0 LOAD_CONST               0 (None)
            3 RETURN_VALUE