Python空生成器函数

2024-04-28 03:44:03 发布

您现在位置:Python中文网/ 问答频道 /正文

在python中,通过将yield关键字放在函数体中,可以很容易地定义迭代器函数,例如:

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

我如何定义一个不产生值的生成器函数(生成0个值),以下代码不起作用,因为python不知道它应该是生成器而不是普通函数:

def empty():
    pass

我可以做点什么

def empty():
    if False:
        yield None

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


Tags: 函数代码infalseforif定义def
3条回答
iter(())

你不需要发电机。来吧伙计们!

Python 3.3(因为我正在进行一次yield from的踢腿,而且@senderle偷走了我的第一个想法):

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

但我不得不承认,我很难想出一个这样的用例,iter([])(x)range(0)不能同样有效。

您可以在生成器中使用return;它停止迭代而不产生任何结果,因此提供了一个显式的替代方案,以使函数超出范围。因此,使用yield将函数转换为生成器,但在它之前使用return在生成任何内容之前终止生成器。

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

我不确定它是否比你现有的更好——它只是用一个no opif语句替换了一个no opyield语句。但它更为地道。注意,仅仅使用yield是行不通的。

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

为什么不直接使用iter(())

这个问题专门询问一个空的生成器函数。因此,我认为这是一个关于Python语法内部一致性的问题,而不是一个关于创建空迭代器的最佳方法的问题。

如果问题实际上是关于创建空迭代器的最佳方法,那么您可能同意使用Zectbumo来代替iter(())。但是,必须注意iter(())不返回函数!它直接返回一个空的iterable。假设您正在使用一个API,它期望一个返回一个iterable的可调用函数。你必须这样做:

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及更高版本中(如DSM所建议的),这:

def empty():
    yield from ()

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

这是一个微妙的区别,但我确实认为基于yield的函数更具可读性和可维护性。

相关问题 更多 >