(test) ? a:b

Chris Angelico rosuav at gmail.com
Wed Oct 22 14:30:01 EDT 2014


On Thu, Oct 23, 2014 at 5:27 AM, Matthew Ruffalo <mmr15 at case.edu> wrote:
> On 10/22/2014 12:40 PM, Chris Angelico wrote:
>> That's true when it's fundamentally arithmetic. But part of that
>> readability difference is the redundancy in the second one. What if it
>> weren't so redundant?
>>
>> 'Negative' if x < 0 else 'Low' if x < 10 else 'Mid' if x < 20 else 'High'
>>
>> You can't easily turn that into a dict lookup, nor indexing. It's
>> either a chained if/elif tree or nested if/else expressions, which
>> come to the same thing.
> No, you can't turn that into a dict lookup, but this is one of the
> canonical use cases for the bisect module:
>
>>>> from bisect import bisect
>>>> breakpoints = [0, 10, 20]
>>>> labels = ['Negative', 'Low', 'Mid', 'High']
>>>> values = [-5, 5, 15, 25]
>>>> [labels[bisect(breakpoints, value)] for value in values]
> ['Negative', 'Low', 'Mid', 'High']
>
> It's also worth noting that using bisect is O(log(n)) instead of O(n),
> but if you're going to hit a point where the asymptotic behavior matters
> I'm sure you will have long since abandoned a manually-written if/elif
> chain.

Indeed. If the performance is making any difference, something's gone
wrong. I'm seeing that as not significantly clearer than the chained
if/else statement or expression: you need a list of breakpoints and a
list of results, which need to be kept in sync. But there's probably
no ideal solution to this.

ChrisA



More information about the Python-list mailing list