为什么不能在收益率中使用yield?

问题描述 投票:-1回答:1

我希望您考虑以下代码:

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的幕后到底发生了什么?

python generator
1个回答
6
投票

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


0
投票

参见此处:What does the "yield" keyword do in Python?

这将详细描述您的问题。简而言之,因为Python插入函数的方式(作为生成对象或返回对象,所以Python中的所有内容都是对象,有些东西会将该对象定义为特定类型。在这种情况下,Yield是生成对象)

TL; DR:您不能在同一功能中使用yieldreturn。在函数中使用任意多次,请不要多次使用。


0
投票

不是,当函数具有让其成为生成器的收益时,您不能使用带有yield的收益,而不能与参数一起使用return

您可能希望将实现更改为

def func(lis):
    for item in lis:
        yield item * 2

-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
    

-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
© www.soinside.com 2019 - 2024. All rights reserved.