以编程方式生成 if elif elif elif else
Programmatically generate if elif elif elif else
我想压缩一些湿代码,如下所示:
if slips[i] < 3000:
ac.setBackgroundColor(wheel['slip'], 0, 0, 0)
# setBackgroundOpacity deliberately omitted here
elif slips[i] < 3700:
ac.setBackgroundColor(wheel['slip'], .2, .4, .2)
ac.setBackgroundOpacity(wheel['slip'], 1)
elif slips[i] < 4100:
ac.setBackgroundColor(wheel['slip'], 0, 1, 0)
ac.setBackgroundOpacity(wheel['slip'], 1)
elif slips[i] < 4500:
ac.setBackgroundColor(wheel['slip'], 0, 0, 1)
ac.setBackgroundOpacity(wheel['slip'], 1)
else:
ac.setBackgroundColor(wheel['slip'], 1, 0, 0)
ac.setBackgroundOpacity(wheel['slip'], 1)
每次重复这段代码时,唯一改变的是背景 canvas(本例中为 wheel['slip']
)和 if elif else 中的数字。
我第一个想把它弄干的是做一些可以像这样使用的东西:
if_replacer(wheel['slip'], slips[i], 3000, 3700, 4100, 4500)
def if_replacer(canvas, value, *args):
# idunno
我的问题是,我将如何以编程方式生成 if elif else?我知道我可以像这样对其进行硬编码:
def if_replacer(canvas, value, c1, c2, c3, c4):
if value < c1:
ac.setBackgroundColor(canvas, 0, 0, 0)
return
elif value < c2:
ac.setBackgroundColor(canvas, .2, .4, .2)
elif value < c3:
ac.setBackgroundColor(canvas, 0, 1, 0)
elif value < c4:
ac.setBackgroundColor(canvas, 0, 0, 1)
else:
ac.setBackgroundColor(canvas, 1, 0, 0)
ac.setBackgroundOpacity(canvas, 1)
但我很感兴趣是否有一种简洁的 Pythonic 方法来实现这一点。
编辑:很多优秀的答案,但遗憾的是我只能将其中一个标记为已接受(尽管所有有效的解决方案都被投票)。我接受了我在代码中实现的答案,但对于偶然发现这个问题的任何其他人,请务必查看其他解决方案,它们都非常出色。并且,感谢所有写下答案的人。
这是一种可能的解决方案。
def least_bound_index(value, bounds):
"""return the least index such that value < bounds[i], or else len(bounds)"""
for i, b in enumerate(bounds):
if value < b:
return i
return i+1
bounds = [3000, 3700, 4100, 4500]
bgcolors = [(0, 0, 0), (.2, .4, .2), (0, 1, 0), (0, 0, 1), (1, 0, 0)]
i = least_bound_index(slips[i], bounds)
ac.setBackgroundColor(wheel['slip'], *bgcolors[i])
if i > 0:
ac.setBackgroundOpacity(wheel['slip'], 1)
请注意,least_bound_index
也可以称为 index_between
,因为您可以想象 [a, b, c, d] 在数字轴上,它会告诉您值落在何处这些选择:
a b c d
^ ^ ^ ^ ^
0 1 2 3 4
万一 'setBackgroundOpacity' 被错误地省略了,或者它是否也包含在第一种情况中并不重要,这是您可能正在寻找的解决方案:
color_map = [ (3000, 0, 0, 0),
(3700, .2, .4, .2),
(4100, 0, 1, 0),
(4500, 0, 0, 1),
(10**10, 1, 0, 0) ]
for i, (c, r, g, b) in enumerate(color_map):
if value < c:
ac.setBackgroundColor(wheel['slip'], r, g, b)
if i > 0:
ac.setBackgroundOpacity(wheel['slip'], 1)
break
编辑:看到关于 setBackgroundOpacity 函数的评论
Edit2:修正了拼写错误并为 10**10 添加了替代解决方案
color_map = [ (3000, 0, 0, 0),
(3700, .2, .4, .2),
(4100, 0, 1, 0),
(4500, 0, 0, 1),
(float("inf"), 1, 0, 0) ]
for i, (c, r, g, b) in enumerate(color_map):
if value < c:
ac.setBackgroundColor(wheel['slip'], r, g, b)
if i > 0:
ac.setBackgroundOpacity(wheel['slip'], 1)
break
c = [[0,0,0],[.2,.4,.2],[0,1,0],[0,0,1]]
threshold = [3000,3700,4100,4500]
if slips[i] >= 4500:
ac.setBackgroundColor(wheel['slip'],1,0,0)
else:
for x in range(4):
if slips[i] < threshold[x]:
ac.setBackgroundColor(wheel['slip'],c[x][0],c[x][1],c[x][2])
break
if slips[i] >= 3000:
ac.setBackgroundOpacity(wheel['slip'], 1)
这是另一种选择,但我个人更喜欢@mpurg 的回答。
我的看法(未经实际 ac...
调用测试):
from functools import partial
mapping = [
(3000, (0, 0, 0), None),
(3700, (.2, .4, .2), 1),
(4100, (0, 1, 0), 1),
(4500, (0, 0, 1), 1),
(float('inf'), (1, 0, 0), 1)
]
def if_replacer(canvas, value, mapping):
set_color = partial(ac.setBackgroundColor, canvas)
set_opacity = partial(ac.setBackgroundOpacity, canvas)
for limit, vals, opacity in lookup:
if value < limit:
set_color(*vals)
if opacity is not None:
set_opacity(opacity)
break
然后,如果出于某种原因您确实必须选择新的范围,那么您可以执行以下操作:
from bisect import insort_left
insort_left(mapping, (4300, (1, 1, 1), 0))
这会将 mapping
更新为:
[(3000, (0, 0, 0), None),
(3700, (0.2, 0.4, 0.2), 1),
(4100, (0, 1, 0), 1),
(4300, (1, 1, 1), 0),
(4500, (0, 0, 1), 1),
(inf, (1, 0, 0), 1)]
def problem1_5(age):
"""Prints according to ages"""
if age(1<7):
print("Have a glass of milk")
elif age(7<21):
print("Have a cake")
elif age>21:
print("Have a martini")
else:
print(end='')
我想压缩一些湿代码,如下所示:
if slips[i] < 3000:
ac.setBackgroundColor(wheel['slip'], 0, 0, 0)
# setBackgroundOpacity deliberately omitted here
elif slips[i] < 3700:
ac.setBackgroundColor(wheel['slip'], .2, .4, .2)
ac.setBackgroundOpacity(wheel['slip'], 1)
elif slips[i] < 4100:
ac.setBackgroundColor(wheel['slip'], 0, 1, 0)
ac.setBackgroundOpacity(wheel['slip'], 1)
elif slips[i] < 4500:
ac.setBackgroundColor(wheel['slip'], 0, 0, 1)
ac.setBackgroundOpacity(wheel['slip'], 1)
else:
ac.setBackgroundColor(wheel['slip'], 1, 0, 0)
ac.setBackgroundOpacity(wheel['slip'], 1)
每次重复这段代码时,唯一改变的是背景 canvas(本例中为 wheel['slip']
)和 if elif else 中的数字。
我第一个想把它弄干的是做一些可以像这样使用的东西:
if_replacer(wheel['slip'], slips[i], 3000, 3700, 4100, 4500)
def if_replacer(canvas, value, *args):
# idunno
我的问题是,我将如何以编程方式生成 if elif else?我知道我可以像这样对其进行硬编码:
def if_replacer(canvas, value, c1, c2, c3, c4):
if value < c1:
ac.setBackgroundColor(canvas, 0, 0, 0)
return
elif value < c2:
ac.setBackgroundColor(canvas, .2, .4, .2)
elif value < c3:
ac.setBackgroundColor(canvas, 0, 1, 0)
elif value < c4:
ac.setBackgroundColor(canvas, 0, 0, 1)
else:
ac.setBackgroundColor(canvas, 1, 0, 0)
ac.setBackgroundOpacity(canvas, 1)
但我很感兴趣是否有一种简洁的 Pythonic 方法来实现这一点。
编辑:很多优秀的答案,但遗憾的是我只能将其中一个标记为已接受(尽管所有有效的解决方案都被投票)。我接受了我在代码中实现的答案,但对于偶然发现这个问题的任何其他人,请务必查看其他解决方案,它们都非常出色。并且,感谢所有写下答案的人。
这是一种可能的解决方案。
def least_bound_index(value, bounds):
"""return the least index such that value < bounds[i], or else len(bounds)"""
for i, b in enumerate(bounds):
if value < b:
return i
return i+1
bounds = [3000, 3700, 4100, 4500]
bgcolors = [(0, 0, 0), (.2, .4, .2), (0, 1, 0), (0, 0, 1), (1, 0, 0)]
i = least_bound_index(slips[i], bounds)
ac.setBackgroundColor(wheel['slip'], *bgcolors[i])
if i > 0:
ac.setBackgroundOpacity(wheel['slip'], 1)
请注意,least_bound_index
也可以称为 index_between
,因为您可以想象 [a, b, c, d] 在数字轴上,它会告诉您值落在何处这些选择:
a b c d
^ ^ ^ ^ ^
0 1 2 3 4
万一 'setBackgroundOpacity' 被错误地省略了,或者它是否也包含在第一种情况中并不重要,这是您可能正在寻找的解决方案:
color_map = [ (3000, 0, 0, 0),
(3700, .2, .4, .2),
(4100, 0, 1, 0),
(4500, 0, 0, 1),
(10**10, 1, 0, 0) ]
for i, (c, r, g, b) in enumerate(color_map):
if value < c:
ac.setBackgroundColor(wheel['slip'], r, g, b)
if i > 0:
ac.setBackgroundOpacity(wheel['slip'], 1)
break
编辑:看到关于 setBackgroundOpacity 函数的评论
Edit2:修正了拼写错误并为 10**10 添加了替代解决方案
color_map = [ (3000, 0, 0, 0),
(3700, .2, .4, .2),
(4100, 0, 1, 0),
(4500, 0, 0, 1),
(float("inf"), 1, 0, 0) ]
for i, (c, r, g, b) in enumerate(color_map):
if value < c:
ac.setBackgroundColor(wheel['slip'], r, g, b)
if i > 0:
ac.setBackgroundOpacity(wheel['slip'], 1)
break
c = [[0,0,0],[.2,.4,.2],[0,1,0],[0,0,1]]
threshold = [3000,3700,4100,4500]
if slips[i] >= 4500:
ac.setBackgroundColor(wheel['slip'],1,0,0)
else:
for x in range(4):
if slips[i] < threshold[x]:
ac.setBackgroundColor(wheel['slip'],c[x][0],c[x][1],c[x][2])
break
if slips[i] >= 3000:
ac.setBackgroundOpacity(wheel['slip'], 1)
这是另一种选择,但我个人更喜欢@mpurg 的回答。
我的看法(未经实际 ac...
调用测试):
from functools import partial
mapping = [
(3000, (0, 0, 0), None),
(3700, (.2, .4, .2), 1),
(4100, (0, 1, 0), 1),
(4500, (0, 0, 1), 1),
(float('inf'), (1, 0, 0), 1)
]
def if_replacer(canvas, value, mapping):
set_color = partial(ac.setBackgroundColor, canvas)
set_opacity = partial(ac.setBackgroundOpacity, canvas)
for limit, vals, opacity in lookup:
if value < limit:
set_color(*vals)
if opacity is not None:
set_opacity(opacity)
break
然后,如果出于某种原因您确实必须选择新的范围,那么您可以执行以下操作:
from bisect import insort_left
insort_left(mapping, (4300, (1, 1, 1), 0))
这会将 mapping
更新为:
[(3000, (0, 0, 0), None),
(3700, (0.2, 0.4, 0.2), 1),
(4100, (0, 1, 0), 1),
(4300, (1, 1, 1), 0),
(4500, (0, 0, 1), 1),
(inf, (1, 0, 0), 1)]
def problem1_5(age):
"""Prints according to ages"""
if age(1<7):
print("Have a glass of milk")
elif age(7<21):
print("Have a cake")
elif age>21:
print("Have a martini")
else:
print(end='')