Python 以编程方式生成if elif elif else

Python 以编程方式生成if elif elif else,python,if-statement,dry,Python,If Statement,Dry,我想浓缩一些湿代码,如下所示: 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(wh

我想浓缩一些湿代码,如下所示:

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)
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)
def if_替换(画布、值、c1、c2、c3、c4):
如果值小于c1:
ac.setBackgroundColor(画布,0,0,0)
返回
elif值
但我感兴趣的是,是否有一种简洁的、类似于python的方法来实现这一点


编辑:有很多很好的答案,但遗憾的是,我只能将其中一个标记为已接受(尽管所有有效的解决方案都经过了投票)。我接受了我在代码中实现的答案,但是对于任何偶然发现这个问题的人来说,一定要看看其他的解决方案,它们都非常优秀。感谢所有写下答案的人。

这里有一个可能的解决方案

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)

如果“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
color_map=[(3000,0,0,0),
(3700, .2, .4, .2), 
(4100, 0, 1, 0), 
(4500, 0, 0, 1), 
(10**10, 1, 0, 0) ]
对于枚举(颜色映射)中的i,(c,r,g,b):
如果值0:
ac.setBackgroundOpacity(车轮[‘打滑’],1)
打破
编辑:查看了有关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
color_map=[(3000,0,0,0),
(3700, .2, .4, .2), 
(4100, 0, 1, 0), 
(4500, 0, 0, 1), 
(浮动(“inf”),1,0,0)]
对于枚举(颜色映射)中的i,(c,r,g,b):
如果值0:
ac.setBackgroundOpacity(车轮[‘打滑’],1)
打破
c=[[0,0,0],[0,0,0],[2,4,2],[0,1,0],[0,0,1]]
阈值=[3000370041004500]
如果滑动[i]>=4500:
ac.setBackgroundColor(车轮['slip'],1,0,0)
其他:
对于范围(4)内的x:
如果滑动[i]<阈值[x]:
ac.setBackgroundColor(车轮['slip',c[x][0],c[x][1],c[x][2])
打破
如果滑动[i]>=3000:
ac.setBackgroundOpacity(车轮[‘打滑’],1)
这是一种选择,但我个人更喜欢@mpurg的答案。

我对它的看法(未测试实际的
ac..
调用):

它将
映射更新为:

[(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问题1_5(年龄):
“按年龄打印”

如果在第一种情况下,你是否故意省略了
ac.setBackgroundOpacity(wheel['slip',1)
?@trevormerifield,他们似乎在“硬编码”中对其进行了特殊包装例如…所以我猜这不仅仅是一条遗漏的线…但我们永远不知道…@Trevormerifield是的,这是经过深思熟虑的我会使用部分函数来减少重复,但除此之外,我认为您现有的结构是最清晰的(即,目前最可维护的)。这可能会产生意外的副作用。一旦找到匹配项,就应该打破循环。是的,我一发布就注意到了这一点。现在修复了,谢谢你一个小错误:
setBackgroundCOlor
应该是
setBackgroundCOlor
。这个解决方案直观且易于遵循,我认为在控制流方面非常python,但是
10**10
让我有点不舒服。事实上,这并不是最大数量的最佳选择。这是一个整洁、专业的解决方案,但不幸的是,我不能使用
functools
,因为这是在精简版Python中运行的-具体来说,它是作为Assetto中的应用程序运行的Corsa.我甚至不能在这里使用
dict.items()
。@DavidTan yowsers-我当然不羡慕你:)我花了很长时间才明白这一点,我想问
return I+1
有什么作用,但我终于想出来,省去了自己的尴尬:如果
value
不在任何范围内,那么它必须是最后一种颜色,因此此行添加一种颜色来选择它。这避免了询问
值是否在最后一个界限和无穷大之间的“无穷大攻击”。在我看来,这是一个相当聪明的解决办法。这是我最后使用的,谢谢!很高兴它对你有用!我还只是在答案中添加了另一种思考方式。
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)
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))
[(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='')