Python空发生器函数

在Python中,可以通过将yield关键字放在函数的主体中来轻松定义一个迭代器函数,例如:

def gen(): for i in range(100): yield i 

我怎样才能定义一个不产生任何值的生成器函数(生成0值),下面的代码不起作用,因为python不知道它应该是一个生成器,而不是一个正常的函数:

 def empty(): pass 

我可以做类似的事情

 def empty(): if False: yield None 

但那会非常难看。 有没有什么好的方法来实现一个空的迭代器函数?

您可以在发生器中使用return一次; 它会停止迭代而不产生任何东西,因此提供了一个明确的替代方法来让函数超出作用域。 所以使用yield来将函数转换成一个生成器,但是在return之前先终止生成器,然后再生成任何东西。

 >>> def f(): ... return ... yield ... >>> list(f()) [] 

我不确定它比你有什么更好的 – 它只是用一个没有操作的yield语句来替代一个没有操作的if语句。 但它更习惯。 请注意,只使用yield不起作用。

 >>> def f(): ... yield ... >>> list(f()) [None] 

为什么不使用iter(())

这个问题具体询问一个空的发电机function 。 出于这个原因,我认为这是一个关于Python语法的内部一致性的问题,而不是关于通常创build空的迭代器的最佳方式的问题。

如果问题实际上是关于创build一个空的迭代器的最好方法,那么你可能会同意Zectbumo关于使用iter(()) 。 然而,观察iter(())不返回函数是很重要的! 它直接返回一个空的迭代。 假设你正在使用一个API,期望一个可返回的可callback的API。 你将不得不做这样的事情:

 def empty(): return iter(()) 

(信用应该去Unutbu提供这个答案的第一个正确的版本。)

现在,你可能会发现上面更清楚,但我可以想象,情况会不太清楚。 考虑一个长长的(人为的)生成器函数定义列表的例子:

 def zeros(): while True: yield 0 def ones(): while True: yield 1 ... 

在这个长长的名单的最后,我宁愿看到一个有yield的东西,就像这样:

 def empty(): return yield 

或者在Python 3.3及更高版本(如DSMbuild议)中,这样做:

 def empty(): yield from () 

yield关键字的出现清楚地表明,这只是另一个生成器函数,与所有其他函数完全相同。 iter(())版本正在做同样的事情需要多一点的时间。

这是一个微妙的差异,但我真的认为基于yield的函数更具可读性和可维护性。

 iter(()) 

不需要发电机。 来吧!

Python的3.3(因为我yield from一脚踢出,因为@senderle偷走了我的第一个想法):

 >>> def f(): ... yield from () ... >>> list(f()) [] 

但是我不得不承认,我很难想出一个用iter([])或者(x)range(0)不能很好地工作的用例。

另一个select是:

 (_ for _ in ()) 

我更喜欢以下内容:

 def foo(): raise StopIteration() yield 

“yield”将其变成一个生成器,而Exception则意味着None不包含在结果中(纯粹是空的结果)。

它必须是一个发电机function? 如果没有,那么怎么样

 def f(): return iter([]) 

做一个空的迭代器的“标准”方式似乎是iter([])。 我build议make []默认参数iter(); 这被拒绝了很好的论点,请参阅http://bugs.python.org/issue25215 – Jurjen

 generator = (item for item in []) 

对于那些实际上需要一个函数,实际上需要一个生成器的人

 empty = lambda: (_ for _ in ())