为什么我不能将yield与return一起使用?

问题描述 投票:0回答:5

我希望您考虑以下代码:

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 function return python-2.x yield
5个回答
9
投票

Python 必须在字节码编译时决定函数是否是生成器。这是因为生成器的语义表明,生成器函数中的任何代码都不会在第一次

next
调用之前运行;生成器函数返回一个生成器迭代器,当调用
next
时,它会运行生成器代码。因此,Python 无法通过运行函数直到遇到
yield
return
来决定它是否应该是生成器;相反,函数中存在
yield
表示该函数是生成器。

在 Python 3 上,这不再是 SyntaxError,但你的函数仍然无条件地是一个生成器。带有参数的

return
现在只意味着生成器中的某些内容,而不是语法错误 - 它决定了生成器上的
yield from
将返回什么。迭代
func([1])
不会产生任何元素,因为生成器永远不会
yield
s。


0
投票

参见这里:Python 中的“yield”关键字有什么作用?

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

TL;DR:您不能在同一函数中使用

yield
return
。在函数中使用其中一个任意多次即可,但不能同时使用两个。


0
投票

不是说,你不能将 return 与yield 一起使用,而是当你的函数有一个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.