考虑这两个功能:
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
答案 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
语句。