Programmatically generate if elif elif elif else
<p>I would like to condense some wet code that looks like this:</p>

<pre><code>if slips[i] &lt; 3000:
    ac.setBackgroundColor(wheel['slip'], 0, 0, 0)
    # setBackgroundOpacity deliberately omitted here
elif slips[i] &lt; 3700:
    ac.setBackgroundColor(wheel['slip'], .2, .4, .2)
    ac.setBackgroundOpacity(wheel['slip'], 1)
elif slips[i] &lt; 4100:
    ac.setBackgroundColor(wheel['slip'], 0, 1, 0)
    ac.setBackgroundOpacity(wheel['slip'], 1)
elif slips[i] &lt; 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)
</code></pre>

<p>Each time this snippet of code is repeated, the only things that change are the background canvas (<code>wheel['slip']</code> in this case), and the numbers in the if elif else's.</p>

<p>My first thought to dry this up was to make something that could be used like this:</p>

<pre><code>if_replacer(wheel['slip'], slips[i], 3000, 3700, 4100, 4500)

def if_replacer(canvas, value, *args):
    # idunno
</code></pre>

<p>My question is, how would I programmatically generate the if elif else's? I know I could hard-code it like so:</p>

<pre><code>def if_replacer(canvas, value, c1, c2, c3, c4):
    if value &lt; c1:
        ac.setBackgroundColor(canvas, 0, 0, 0)
        return
    elif value &lt; c2:
        ac.setBackgroundColor(canvas, .2, .4, .2)
    elif value &lt; c3:
        ac.setBackgroundColor(canvas, 0, 1, 0)
    elif value &lt; c4:
        ac.setBackgroundColor(canvas, 0, 0, 1)
    else:
        ac.setBackgroundColor(canvas, 1, 0, 0)
    ac.setBackgroundOpacity(canvas, 1)
</code></pre>

<p>But I'm interested if there is a succinct and Pythonic method to accomplish this.</p>

<p>edit: A lot of excellent answers, but alas I can only mark one of them as accepted (though all valid solutions were upvoted). I accepted the answer that I implemented in my code, but for anyone else who stumbles across this question, do take a look at the other solutions, they're all excellent. And, thanks to everyone who wrote an answer.</p>

<p>My take on it (untested as to the actual <code>ac...</code> calls):</p>

<pre><code>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 &lt; limit:
            set_color(*vals)
            if opacity is not None:
                set_opacity(opacity)
            break
</code></pre>

<p>Then if for some reason you do have to pick up new ranges, then you can do something like:</p>

<pre><code>from bisect import insort_left
insort_left(mapping, (4300, (1, 1, 1), 0))
</code></pre>

<p>Which'll update <code>mapping</code> to be:</p>

<pre><code>[(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)]
</code></pre>

python if-statement dry