为什么不能通过参数切换函数生成器的行为?

时间:2017-03-01 19:45:06

标签: python python-3.x generator

考虑这两个功能:

def foo():
    x = 0
    while True:
        yield x
        x += 1

def wrap_foo(limit=10, gen=True):
    fg = foo()
    count = 0
    if gen:
        while count < limit:
            yield next(fg)
            count += 1
    else:
        return [next(fg) for _ in range(limit)]=

foo()是一个生成器,而wrap_foo()只是限制了生成的数据量。我正在尝试让包装器表现为具有gen=True的生成器,或者作为常规函数将所有生成的数据直接放入内存中使用kwarg gen=False

常规的生成器行为正如我所期望的那样:

In [1352]: [_ for _ in wrap_foo(gen=True)]
Out[1352]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

但是,使用gen=False时,不会生成任何内容。

In [1351]: [num for num in wrap_foo(gen=False)]
Out[1351]: []

似乎Python根据yield语句的存在将函数预先分类为生成器(后一个示例在yield被注释掉时效果很好。)

这是为什么?我想了解这里的机制。我正在运行3.6

2 个答案:

答案 0 :(得分:7)

  

似乎Python根据yield语句的存在将函数预先分类为生成器

是的,这正是发生的事情。在功能定义时确定wrap_foo是生成器。您可以考虑使用生成器表达式:

def wrap_foo(limit=10, gen=True):
    fg = foo()
    if gen:
        return (next(fg) for _ in range(limit))
    else:
        return [next(fg) for _ in range(limit)]

答案 1 :(得分:3)

  

似乎Python将函数预先分类为基于生成器的函数   关于收益率陈述的存在(后一个例子完美地运作   如果收益率被评论出来。)

     

为什么会这样?

因为Python不能等到函数实际执行yield来判断它是否是生成器。首先,生成器被定义为在第一个next之前不执行任何代码。其次,如果生成器碰巧没有生成任何元素,它可能永远不会实际到达任何yield语句。