是否有可能在传递列表时生成一个生成生成器的函数,但是在给定单个值时会返回?
以此为例:
def duty2015(x):
if type(x) in [list, np.ndarray]:
for xi in x:
yield new_duty(xi)
else:
sd = 0
if x <= 120000:
return sd
elif x <= 250000:
return (x-125000) * 0.02
elif x <= 925000:
return 2500 + (x-250000)*0.05
elif x <= 1500000:
return 36250 + (x-925000)*0.1
else:
return 93750 + (x-1500000)*0.12
显然这不起作用,我得到SyntaxError: 'return' with argument inside generator
错误。
我意识到我可以做这样的事情:
def duty2015(x):
if type(x) in [list, np.ndarray]:
for xi in x:
for result in duty2015(xi):
yield result
else:
sd = 0
if x <= 125000:
yield sd
elif x <= 250000:
yield (x-125000) * 0.02
elif x <= 925000:
yield 2500 + (x-250000)*0.05
elif x <= 1500000:
yield 36250 + (x-925000)*0.1
else:
yield 93750 + (x-1500000)*0.12
但是当我在单个物品上调用它时,它会给我一个发电机,而我只是在它被调用更大的物品时才会得到它。
显然我可以把它作为一个列表,但这又不是最佳的。
对于下面答案中的评论,这样的事情会更好:
def duty_new(x, generator=False):
if type(x) in [list, np.ndarray]:
if generator:
return (duty_new(xi) for xi in x)
else:
return [duty_new(xi) for xi in x]
else:
sd = 0
if x <= 125000:
return sd
elif x <= 250000:
return (x-125000) * 0.02
elif x <= 925000:
return 2500 + (x-250000)*0.05
elif x <= 1500000:
return 36250 + (x-925000)*0.1
else:
return 93750 + (x-1500000)*0.12
因此,在正常使用下,它将具有可预测的行为或返回与传递给它的相同类型的参数(至少对于合理的参数,并且可能是因为它不会仅仅遍历numpy数组),但如果需要发电机,可以明确要求它?
答案 0 :(得分:5)
返回一个生成器表达式,如下所示
def duty2015(x):
if isinstance(x, list) or isinstance(x, np.ndarray):
return (result for xi in x for result in duty2015(xi))
else:
...
...
现在,每当您使用单个元素调用duty2015
时,您将获得单独的值,否则您将获得一个生成器表达式,该表达式必须使用next
协议进行迭代。
就个人而言,我觉得你的第二个版本是好的并且它是一致的,因为它使duty2015
成为一个生成器函数,而且正如Martijn Pieters在评论中所提到的那样,它没有调用者猜测它得到了什么回来,更好地坚持下去。
注意:第一版和第二版的代码不同。我选择第二个版本中的代码来显示这个想法。
答案 1 :(得分:2)
这样怎么回事? :
def new_fun(x):
return x + 1
def duty2015(x):
if type(x) is list:
return (new_fun(i) for i in x)
else:
sd = 0
if x <= 120000:
return sd
elif x <= 250000:
return (x-125000) * 0.02
elif x <= 925000:
return 2500 + (x-250000)*0.05
elif x <= 1500000:
return 36250 + (x-925000)*0.1
else:
return 93750 + (x-1500000)*0.12
print duty2015([1,2,3])
print (1)
输出:
<generator object <genexpr> at 0x10be06b40>
1
这样你就可以使用return获取生成器对象。
答案 2 :(得分:0)
您可以返回另一个作为生成器的函数的结果,如下所示:
def dolist(li):
for el in li:
yield el * 2
def either(x):
if isinstance(x, list):
return dolist(x)
else:
return x * 2
print either(4) # prints 8
print list(either([2,3])) # prints [4,6]
答案 3 :(得分:0)
您可以从函数中返回生成器。通过
def duty2015(x):
if isinstance(x, list) or isinstance(x, np.ndarray):
return (new_duty(xi) for xi in x)
else:
...
或使用辅助生成器函数:
def duty_gen(x):
for xi in x:
yield new_duty(xi)
def duty2015(x):
if isinstance(x, list) or isinstance(x, np.ndarray):
return duty_gen(x)