A few weeks ago, I introduced you to functional programming in Python. Today, I'd like to go further into this topic and show you so more interesting features.

# Lambda Functions

What do we call lambda functions? They are in essence anonymous functions. In order to create them, you must use the `lambda` statement:

``````>>> lambda x: x
<function <lambda> at 0x102e23620>
``````

In Python, lambda functions are quite limited. They can take any number of arguments; however they can contain only one statement and be written on a single line.

They are mostly useful to be passed to high-order functions, such as `map()`:

``````>>> list(map(lambda x: x * 2, range(10)))
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
``````

This will apply the anonymous function `lambda x: x * 2` to every item returned by `range(10)`.

# functools.partial

Since lambda functions are limited to being one line long, it's often that they are used to specialize longer version of an existing function:

``````def between(number, min=0, max=1000):
return max > number > min

# Only returns number between 10 and 1000
filter(lambda x: between(x, min=10), range(10000))
``````

Our lambda is finally just a wrapper of the `between` function with one of the argument already set. What if we would have a better way, without the various lambda limitations, to write that? That's where `functools.partial` comes handy.

``````import functools
def between(number, min=0, max=1000):
return max > number > min

# Only returns number between 10 and 1000
atleast_10_and_upto = functools.partial(between, min=10)
# Return number betweens 10 and 1000
filter(atleast_10_and_upto, range(10000))

# Return number betweens 10 and 20
filter(lambda x: atleast_10_and_upto(x, max=20), range(10000))
``````

The `functools.partial` function returns a specialized version of the `between` function, where `min` is already set. We can store them in a variable, use it, reuse it, as much as we want. We can pass it a `max` argument, as shown in the second part — using a `lambda`! You can mix and matches those two as you prefer and what seems clearer for you.

# Common lambda

There is a type of lambda function that is pretty common: the attribute or item getter. They are typically used a `key` function for sorting or filtering.

Here's a list of 200 tuples containing two integers `(i1, i2)`. If you want to use only `i2` as the sorting key, you would write:

``````mylist = list(zip(range(40, 240), range(-100, 100)))

sorted(mylist, key=lambda i: i)
``````

Which works fine, but make you use `lambda`. You could rather use the `operator` module:

``````import operator

mylist = list(zip(range(40, 240), range(-100, 100)))

sorted(mylist, key=operator.itemgetter(1))
``````

This does the same thing, except it avoids using `lambda` altogether. Cherry-on-the-cake: it is actually 10% faster on my laptop.

I hope that'll make you write more functional code!