-3

我希望您考虑以下代码:

def func(alist):
    if len(alist) == 1:
        return arg * 2
    for item in alist:
        yield item * 2

当我运行它时,我得到这个错误:

SyntaxError: 'return' with argument inside generator

现在,我意识到我不能这样做。但是,我想知道为什么。导致 Python 抛出的幕后究竟发生了SyntaxError什么?

4

5 回答 5

7

Python 必须在字节码编译时决定一个函数是否是生成器。这是因为生成器的语义表明生成器函数中的任何代码都不会在第一次next调用之前运行。生成器函数返回一个生成器迭代器,当next被调用时,它运行生成器代码。因此,Python 不能通过运行它直到它遇到 ayield或 a来决定一个函数是否应该是一个生成器return;相反,函数中存在 ayield表示该函数是生成器。

于 2013-08-13T18:11:51.890 回答
0

请参阅此处:“yield”关键字在 Python 中的作用是什么?

这详细描述了您的问题。简而言之,因为 Python 将解释函数的方式(作为生成对象或返回对象,Python 中的一切都是对象,有些东西会将那个对象定义为特定类型。在这种情况下,Yield 是生成对象)

TL;DR:你不能在同一个函数中使用yieldand 。return在函数中尽可能多地使用其中之一,而不是两者都使用。

于 2013-08-13T17:49:40.600 回答
0

不是这样,您不能将 return 与 yield 一起使用,而是当您的函数具有 yield 使其成为生成器时,您不能将 return 与参数一起使用

您可能希望将实现更改为

def func(lis):
    for item in lis:
        yield item * 2
于 2013-08-13T17:49:49.603 回答
-1

你想要的确实是可能的:

def func(lis):
    if len(lis) == 1:
        return lis[0] * 2
    else:
        return (item * 2 for item in lis)

这在一种情况下返回一个值,在另一种情况下返回一个生成器。

但请注意,这会导致问题:在每次通话中,您都必须做出区分

res = func(lis)
if len(lis) == 1:
    print res # my value
else:
    for i in res: print i # several values

将这两个用例区分开来更为可取:

  1. 你可以做

    def func(val):
        return val * 2
    

    并且,当您需要时,请执行以下任一操作

    reslist = [func(i) for i in lis]
    resgen = (func(i) for i in lis)
    

    或者

  2. 你可以做

    def func(lis):
        for item in lis:
            yield lis[0] * 2
    
    def func1(val):
        for i in func([val]):
            return i # returns the first value
    
于 2013-08-13T18:01:41.427 回答
-1

其他答案已经解释了产量/回报问题。您可以使用它map来简化此操作:

def func(lis):
    return map(lambda item: item * 2, lis)
   # similar to: return [item * 2 for item in lis]

当然,这将始终返回一个列表,因为lis它是一个列表,即使它只有一个项目。您可以将其更改为复合语句:

def func(lis):
    return map(lambda item: item * 2, lis) if len(lis) > 1 else lis[0] * 2
于 2013-08-13T18:29:23.017 回答