2
#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

4 回答 4

2

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

于 2013-07-24T04:47:37.800 回答
2

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

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

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

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

我想不出解释器有什么理由决定哪个部分是生成器。这很难,我认为这是程序员的责任。我什至怀疑在生成器中返回值是否是一个好的实现。

于 2013-07-24T04:57:05.193 回答
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
于 2013-07-24T04:56:05.277 回答
0

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

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

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

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

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

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

于 2013-07-24T05:14:55.803 回答