我希望您考虑以下代码:
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
?
答案 0 :(得分:5)
Python必须在字节码编译时决定函数是否是生成器。这是因为生成器的语义表明生成器函数中的所有代码都没有在第一个next
调用之前运行;生成器函数返回一个生成器迭代器,当调用next
时,它运行生成器代码。因此,Python无法通过运行它来决定函数是否应该是生成器,直到它到达yield
或return
;相反,函数中存在yield
表示函数是生成器。
答案 1 :(得分:1)
见这里:What does the "yield" keyword do in Python?
这详细描述了您的问题。 简而言之,因为Python将插入函数的方式(作为生成对象或返回对象,Python中的所有内容都是对象,有些东西会将该对象定义为特定类型。在这种情况下,Yield是生成对象)
TL; DR:您不能在同一个函数中使用yield
和return
。你可以在函数中使用任意一次,而不是两者都使用。
答案 2 :(得分:1)
不是这样,你不能使用带有yield的return,而是当你的函数有一个使它成为生成器的yield时,你不能使用带参数的return
您可能希望将实施更改为
def func(lis):
for item in lis:
yield item * 2
答案 3 :(得分:0)
你想要的确实是可能的:
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
使两个用例区别开来更为可取:
你可以做到
def func(val):
return val * 2
并且,当您需要时,执行
中的任何一个reslist = [func(i) for i in lis]
resgen = (func(i) for i in lis)
或
你可以做到
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
答案 4 :(得分:0)
其他答案已经解释了收益/回报问题。你可以使用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