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 |
如果可以,但似乎是有线的。谁有更好的主意?
谢谢,
- 这就是Python的工作原理。我不认为你真的需要最后一个return在那里。python不是c。别指望他们也能这样做。
- 没有yield的函数不是生成器。因此,您的第一个示例只返回None,并尝试对其进行迭代。
- @那不是发电机。它是一个无法识别的生产对象。虽然正如我在菲哈格的回答中所说,这不太重要。
1 2 3
| def generate_nothing():
return
yield |
- 不过,这将在linters中创建一个无法访问的代码警告。
处理这一问题的一个好方法是引发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个或更少的列表。
- 请注意,从3.6开始,这是一个坏主意,因为随着PEP 479的实施,StopIteration将转换为RuntimeError,以防止在使用子发电机时出现问题。
- 在任何版本中,这都是一个坏主意;仅限于return。
- 虽然这是功能性的(目前),但return更好;所描述的功能甚至包括在返回文档中。
1 2
| def generate_nothing():
return iter([]) |
- 或3.x中的xrange(0)(range(0))。
- 这两种方法的速度都是return; yield的两倍。但请注意,这些将返回类型为和的对象,这两个类型都是object的直接子类型,因此它们不是生成器。没关系。仅仅是学术上的兴趣:—)
- @克里斯:在《python3》中,我只加快了20-30%的速度,但从质量上看,它似乎稍微不太像一种记忆压力(不是严格的测试:z=[list(f()) for _ in range(10**7)])。
有趣的是两个函数都有相同的字节码。当字节码编译器找到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 |
- 甜的。它甚至不为yield语句生成字节码
- @jbernado:hmm,我在python 3中看到了这一点。起初我想,如果给false赋一个不同的值,这将是一个非常明显的问题。我忘记了在python 3中,True和False是关键字。对于同一个字节码,我认为区别在于:f.__code__.co_flags == 67和g.__code__.co_flags == 99。这意味着第六位标志将其标记为生成器。为批评你道歉-但是你现在真的应该把它标记为python 3,因为它产生了相同的字节代码。
- @Chris我已经在我的答案中做了一个评论:)在python 2中,您可以使用0而不是false
- 呵呵?它们根本不一样。再次检查结果。你在某个地方犯了个错误。
- @Chris是的,python2不优化它,因为false不是关键字,也可能不是一个错误值。Python 3。