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 ())