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[1])
```

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!