Skip to main content

Python Cheat Sheet: Lambdas

Do you think list comprehensions are a tricky topic? After reading this post, you may well change your mind about what counts as “complicated” in Python.

Lambdas

A lambda is a small function defined right where you need it, typically for light data-processing jobs. There are two main reasons to use them:

  • Speed: a compiler can optimize them, first by eliminating an actual function call, and then by opening the door to further internal code re-arrangements.
  • Brevity: you write less code.

Here is a lambda that squares a number:

g = lambda x: x ** 2    # e.g. g(3) yields 9

Lambdas are most often paired with the data-processing functions filter, map and reduce.

Filtering

To keep only part of an input, filter combined with a lambda works nicely:

print filter(lambda x: x % 2 == 0, xrange(0, 11))
# [0, 2, 4, 6, 8, 10]

Transformation

To apply a transformation to every element of the input, use map:

print map(lambda x: x * 2, xrange(0, 11))
# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

Summarizing

To boil the whole input down to a single result, use reduce. Note that the lambda must accept two arguments: at first it receives the first two elements, and afterwards it receives the previous result plus the next element, until the input runs out.

print reduce(lambda x, y: x + y, xrange(0, 11))
# 55    # 1 + 2 + ... + 10

Now for the more serious material.

MapReduce in Python

print reduce(lambda x, y: x + y, map(lambda x: x * 2, xrange(0, 11)))
# 110    # 1*2 + 2*2 + ... + 10*2

The Intersection of Two Lists

def intersection(A, B):
    S = set(A)
    return filter(lambda x: x in S, B)

An answer like this probably isn’t what an interviewer expects. If you’re in an interview, make sure you can explain what’s happening before you write it down (for example, how a set works and what the complexity is in big O notation).

Removing Duplicates from a List

If the order of the remaining unique items doesn’t matter, calling set(A) is enough. Otherwise, we need to get creative:

def dedup(A):
    S = set()
    return filter(lambda x: x not in S and None == S.add(x), A)

A set’s add method always returns None, which evaluates to boolean False. To make the logic work, a small hack is needed (S.add() == None).

Also note that this solution keeps the first occurrence of each element and rejects the later duplicates. Solutions that keep the last or the n-th occurrence exist, but they’re much easier to write when the order of elements in the result doesn’t matter:

def dedup_last_unordered(A):
    S = set()
    map(lambda x: ((x in S and None == S.remove(x)) or True) and None == S.add(x), A)
    return S

As you can see, that version is pushing past what lambdas are meant for. Writing it the “normal” way is much clearer:

def dedup_last_unordered(A):
    S = set()
    for i in A:
        if i in S:
            S.remove(i)
        S.add(i)
    return S

A solution for the n-th duplicate can’t be written purely with lambdas, because it needs a counter that is assigned and incremented, and lambdas don’t allow that. A “normal” approach would use a dictionary that stores the counter as the value, but I think it’s best to stop here.

That’s all for today. Hope you enjoyed it!