Chapter 13
We can use dictionary keys and the lambda objects to create a very complex set of
conditions. Here's a way to express the factorial function as expressions:
def fact(n):
f= { n == 0: lambda n: 1,
n == 1: lambda n: 1,
n == 2: lambda n: 2,
n > 2: lambda n: fact(n-1)*n }[True]
return f(n)
This rewrites the conventional if, elif, elif, and else sequence of statements into
a single expression. We've decomposed it into two steps to make what's happening
slightly clearer.
In the first step, we'll evaluate the various conditions. One of the given conditions
will evaluate to True, the others should all evaluate to False. The resulting
dictionary will have two items in it: a True key with a lambda object and a False key
with a lambda object. We'll select the True item and assign it to the f variable.
We used lambdas as the values in this mapping so that the value expressions aren't
evaluated when the dictionary is built. We want to evaluate just one of the value
expressions. The return statement evaluates the one expression associated with the
True condition.
Exploiting non-strict dictionary rules
A dictionary's keys have no order. If we try to create a dictionary with multiple
items that share a common key value, we'll only have one item in the resulting
dict object. It's not clear which of the duplicated key values will be preserved,
and it shouldn't matter.
Here's a situation where we explicitly don't care which of the duplicated keys is
preserved. We'll look at a degenerate case of the max() function, it simply picks the
largest of two values:
def max(a, b):
f = {a >= b: lambda: a, b >= a: lambda: b}[True]
return f()
In the case where a == b, both items in the dictionary will have a key of the True
condition. Only one of the two will actually be preserved. Since the answer is the same,
it doesn't matter which is kept and which is treated as a duplicate and overwritten.