如何编写从不产生任何东西的Python生成器函数

时间:2011-06-07 14:15:24

标签: python generator yield

我想编写一个从未真正产生任何东西的Python生成器函数。基本上它是一个“无所事事”的插件,可以被其他代码用来调用生成器(但并不总是需要它的结果)。到目前为止,我有这个:

def empty_generator():
    # ... do some stuff, but don't yield anything
    if False:
        yield

现在,这可行,但我想知道是否有更具表现力的方式来说同样的事情,即声明一个函数是一个生成器,即使它永远不会产生任何值。我上面使用的技巧是在我的函数中显示Python一个yield语句,即使它无法访问。

4 个答案:

答案 0 :(得分:32)

另一种方式是

def empty_generator():
    return
    yield

不是“更具表现力”,而是更短。 :)

请注意,iter([])或简称[]也可以。

答案 1 :(得分:15)

更短的解决方案:

def empty_generator():
  yield from []

答案 2 :(得分:1)

修改

这不起作用 - 阅读评论


你不能只yield None吗?似乎对我来说更容易阅读。

答案 3 :(得分:1)

为了获得最大的可读性和可维护性,我会优先考虑一个位于函数顶部的结构。所以要么

  1. 您原来的 if False: yield 构造,但被提升到第一行,或者
  2. 一个单独的装饰器,它将生成器行为添加到非生成器可调用对象中。

(假设你不只是需要一个可调用的,它做了一些事情然后返回一个空的迭代器/迭代器。如果是这样,那么你可以只使用一个常规函数和 return ()/return iter(()) 在结束。)

想象一下你的代码的读者会看到:

def name_fitting_what_the_function_does():
    # We need this function to be an empty generator:
    if False: yield

    # that crucial stuff that this function exists to do

将此放在顶部会立即提示此函数的每个读者注意此细节,这会影响整个函数 - 影响对该函数的行为和用法的期望和解释。

你的函数体有多长?不止几行?那么作为一个读者,如果我直到最后都没有得到这个函数是一个生成器的提示,我会对作者感到愤怒和谴责,因为我可能会花费大量的精神成本在我的脑海中编织一个基于假设这是一个常规函数 - 理想情况下,生成器中的第一个 yield 应该立即可见,当您甚至不知道要查找它时.

此外,在超过几行的函数中,函数开头的构造更值得信赖 - 我相信任何看过函数的人都可能见过它的第一个每次他们看它时都排队。这意味着如果那条线出错或断线,有人会发现它的可能性更高。这意味着我可以不那么警惕整个东西实际上已损坏但以一种使损坏不明显的方式使用的可能性。

如果您与非常熟悉 Python 工作原理的人一起工作,您甚至可以忽略该评论,因为对于那些立即记得 yield 是 Python 将函数转换为生成器,很明显这是效果,也可能是意图,因为没有其他原因可以使正确的代码具有未执行的yield

或者,你可以走装饰者路线:

@generator_that_yields_nothing
def name_fitting_what_the_function_does():
    # that crucial stuff for which this exists


def generator_that_yields_nothing(wrapped):
    @functools.wraps(wrapped)
    def wrapper_generator():
        if False: yield
        wrapped()
    return wrapper_generator