为什么Python解释器不会隐式创建生成器?

时间:2013-07-24 04:43:09

标签: python generator yield

#def func(param):
#    if param < 0:
#        return "test"
#    i = 0
#    while i < param:
#        yield i
#        i += 1
def func(param):
    if param < 0:
        return "test"
    def gen(n):
        i = 0
        while i < param:
            yield i
            i += 1
    return gen(param)

print(func(-1))
print(func(3))
g = func(3)
for i in range(0, 3):
    print(next(g))

有没有理由说Python解释器无法隐式地将注释代码转换为实际代码?这似乎应该被允许,但我想知道有什么影响使他们选择不允许这样做。

4 个答案:

答案 0 :(得分:2)

当你调用一个生成器函数时,你知道它将返回什么类型的对象 - 一个生成器。如果我们允许生成器函数到return,那么在开始迭代生成器之前你必须检查返回值的类型,所以你不再有生成器函数 - 只是一个函数可能会返回一个发电机。

答案 1 :(得分:2)

在python2.x中,你不能在生成器中返回一些内容:

>>> def func():
...     return 3
...     yield 3
... 
  File "<stdin>", line 3
SyntaxError: 'return' with argument inside generator
>>> 

在python3.x中,在生成器中使用return意味着引发StopIteration(<something>)

>>> def func():
...     return 3
...     yield 3
... 
>>> func().__next__()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration: 3
>>> 

我无法想到解释器决定哪个部件是发电机的任何理由。这很难,我认为这是程序员的责任。我甚至怀疑在生成器中返回值是否是一个很好的实现。

答案 2 :(得分:0)

生成器被声明为函数但不同, 你不能在生成器中使用return语句 你应该做的是:

def func(param):
    if param < 0:
        yield "test"
        raise StopIteration()
    i = 0
    while i < param:
        yield i
        i += 1

更好的推动力将是:

def func(param):
    if param < 0:
        raise ValueError("param must be a positive number")
    i = 0
    while i < param:
        yield i
        i += 1

答案 3 :(得分:0)

原因很简单,如果def包含yield语句,它会创建一个生成器:

http://www.python.org/dev/peps/pep-0255/

  

yield语句只能在函数内部使用。一个功能   包含一个yield语句称为生成器函数。一台发电机   函数在所有方面都是普通的函数对象,但具有   新的CO_GENERATOR标志在代码对象的co_flags成员中设置。

这就是解释器如何区分常规函数和生成器函数。它易于实现,易于推理(“如果它包含yield,它是一个生成器”)

您描述的“条件生成器”行为实现起来要复杂得多,并且在某些情况下不可取(可能条件应该在生成器的第一次迭代内发生,或者它可能在您调用{ {1}})

您的其他代码会返回生成器或字符串。如果这是你想要的界面,它似乎是一个非常好的解决方案(但没有一个真实的例子很难提出实用的建议)