Welcome, guest | Sign In | My Account | Store | Cart

Although Python now has something similar to ternary operator with the result if ... else other result construction and this allows chaining (adding additional conditions on the if side, this soon becomes unreadable. A common use case is to filter values by ranges so I wrote the following when porting some code from PHP once I found I no longer understand the logic for a simple three-way filter.

Python, 29 lines
 ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29``` ``` def range_comparison(op, checks, value, default=None): """ An extensible ternary operator Takes an operator such as op.lt checks are tuples of sentinel values and results and must be supplied in the right order to suit the operator and prevent it matching greedily. ie. with lt checks must be in ascending order and descending or for gt """ for sentinel, result in checks: if op(value, sentinel): return result return default class TestRangeComparison(TestCase): def make_one(self): from ..utils import range_comparison return range_comparison def test_lt(self): from operator import lt FUT = self.make_one() checks = [(10, "less than 10"), (20, "less than 20"), (100, "less than 100")] self.assertEqual(FUT(lt, checks, 5), "less than 10") self.assertEqual(FUT(lt, checks, 10), "less than 20") self.assertEqual(FUT(lt, checks, 50), "less than 100") self.assertFalse(FUT(lt, checks, 100)) ```

It's very easy to describe filtering by range, say egg sizes, but surprisingly tricky to code this in an elegant and compact manner because you cannot use dictionary dispatch for range membership.

Simple identity-based testing can be done using dictionaries:

``````if a == 10:
print("a is ten")
elif a == 20:
print("a is twenty")
elif a == 30:
print("a is thirty")
else:
print("don't recognise a")
``````

Can be written using dictionaroes

``````comp = dict(
(10, "a is ten"),
(20, "a is twenty"),
(30, "a is thirty"),
)

print comp.get(a, "don't recognise a")
``````

This is great because it is infinitely extensible but low on copy & paste typing so hopefully a source of fewer errors, and, with lots of cases, possibly faster.

But you cannot use this for ranges, say egg sizes. It is surprisingly tricky to code this in an elegant and compact manner. But fortunately Python has the operator module which allows operators to be treated as objects for programmatic manipulation.

#### 1 comment

Charlie Clark (author) 9 years, 6 months ago

Just spotted the invalid import in the Test

``````def make_one(self):
return range_comparison
``````

Should fix it or direct assignment of FUT to range_comparison

 Created by Charlie Clark on Wed, 6 Jun 2012 (MIT)