Python空生成器函数

Python空生成器函数,python,generator,Python,Generator,在python中,通过将yield关键字放在函数体中,可以轻松定义迭代器函数,例如: def gen(): for i in range(100): yield i 如何定义一个不产生值(生成0个值)的生成器函数,以下代码不起作用,因为python无法知道它应该是生成器而不是普通函数: def empty(): pass 我可以做类似的事情 def empty(): if False: yield None 但那将是非常丑陋的。有什么

在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())
[]
我不确定它是否比你现在拥有的要好得多——它只是用一个no-op
yield
语句替换了一个no-op
if
语句。但它更地道。请注意,仅使用
yield
不起作用

>>> def f():
...     yield
... 
>>> list(f())
[None]
为什么不直接使用iter(())? 此问题专门询问空生成器函数。因此,我认为这是一个关于Python语法内部一致性的问题,而不是一个关于创建空迭代器的最佳方法的问题

如果问题实际上是关于创建空迭代器的最佳方法,那么您可能同意使用
iter(())
。然而,重要的是要注意,
iter(())
不返回函数!它直接返回一个空的iterable。假设您正在使用一个API,该API需要一个可调用函数,该函数每次调用时都返回一个iterable,就像普通的生成器函数一样。您必须执行以下操作:

def empty():
    return iter(())
def empty():
    return
    yield
(给出此答案的第一个正确版本应归功于。)

现在,你可能会发现上面的内容更清晰,但我可以想象在什么情况下,它会变得不那么清晰。考虑一个长的(设计的)生成器函数定义的例子:

def zeros():
    while True:
        yield 0

def ones():
    while True:
        yield 1

...
在这个长长的列表的末尾,我更希望看到一些带有
收益率的东西,比如:

def empty():
    return iter(())
def empty():
    return
    yield
或者,在Python3.3及更高版本中(如所建议),这是:

yield
关键字的出现,一眼就能清楚地看出,这只是另一个生成器函数,与所有其他函数完全相同。需要更多的时间才能看到
iter(())
版本也在做同样的事情

这是一个微妙的区别,但我诚实地认为基于
的函数更可读和可维护


还可以从中看到这个很棒的答案,它使用
dis
来说明这种方法更可取的另一个原因:它在编译时发出的指令最少。

您可以在生成器中使用
返回
一次;它停止迭代而不产生任何结果,因此提供了一种明确的替代方法,以避免函数超出范围。因此,使用
yield
将函数转换为生成器,但在函数前面使用
return
在生成任何内容之前终止生成器

>>> def f():
...     return
...     yield
... 
>>> list(f())
[]
我不确定它是否比你现在拥有的要好得多——它只是用一个no-op
yield
语句替换了一个no-op
if
语句。但它更地道。请注意,仅使用
yield
不起作用

>>> def f():
...     yield
... 
>>> list(f())
[None]
为什么不直接使用iter(())
? 此问题专门询问空生成器函数。因此,我认为这是一个关于Python语法内部一致性的问题,而不是一个关于创建空迭代器的最佳方法的问题

如果问题实际上是关于创建空迭代器的最佳方法,那么您可能同意使用
iter(())
。然而,重要的是要注意,
iter(())
不返回函数!它直接返回一个空的iterable。假设您正在使用一个API,该API需要一个可调用函数,该函数每次调用时都返回一个iterable,就像普通的生成器函数一样。您必须执行以下操作:

def empty():
    return iter(())
def empty():
    return
    yield
(给出此答案的第一个正确版本应归功于。)

现在,你可能会发现上面的内容更清晰,但我可以想象在什么情况下,它会变得不那么清晰。考虑一个长的(设计的)生成器函数定义的例子:

def zeros():
    while True:
        yield 0

def ones():
    while True:
        yield 1

...
在这个长长的列表的末尾,我更希望看到一些带有
收益率的东西,比如:

def empty():
    return iter(())
def empty():
    return
    yield
或者,在Python3.3及更高版本中(如所建议),这是:

yield
关键字的出现,一眼就能清楚地看出,这只是另一个生成器函数,与所有其他函数完全相同。需要更多的时间才能看到
iter(())
版本也在做同样的事情

这是一个微妙的区别,但我诚实地认为基于
的函数更可读和可维护

另请参见使用
dis
来说明此方法更可取的另一个原因的伟大答案:它在编译时发出的指令最少。

Python3.3(因为我从
kick中获得了
收益,而且@senderle偷走了我的第一个想法):


但我必须承认,我很难想出一个这样的用例,
iter([])
(x)range(0)
不会同样好用。

python3.3(因为我从
kick中获得了
收益,而且@senderle偷走了我的第一个想法):


但我必须承认,我很难想出一个这样的用例,对于这个用例,
iter([])
(x)range(0)
不能同样好地工作。

它必须是一个生成器函数吗?如果没有,那怎么办

def f():
    return iter(())

它一定是发电机功能吗?如果没有,那怎么办

def f():
    return iter(())
另一个选择是:

(_ for _ in ())
另一个选择是:

(_ for _ in ())
你不需要发电机。来吧,伙计们

generator = (item for item in [])
你不需要一个g