15.8. Function Lambda

15.8.1. Rationale

  • Lambda - Anonymous functions

  • When function is used once

  • When function is short

  • You don't need to name it (hence it is anonymous)

lambda

Anonymous function

15.8.2. Syntax

lambda <arguments>: <expression>

Lambda Expressions:

>>> f = lambda x: x+1
>>> f = lambda x,y: x+y

Equivalent functions:

>>> def f(x):
...     return x+1
>>> def f(x,y):
...     return x+y

15.8.3. Convention

  • Usually parameters are named x and y

  • Use shortest code possible

  • Do not assign lambda to variable

  • Lambda is anonymous function and it should stay anonymous. Do not name it

  • PEP 8 -- Style Guide for Python Code: "Always use a def statement instead of an assignment statement that binds a lambda expression directly to an identifier". Lambda is anonymous function and it should stay anonymous. Do not name it.

  • Usually there are no spaces in lambda expressions (to make code shorter)

Bad:

>>> square = lambda x: x**2
>>> square(4)
16

Good:

>>> def square(x):
...     return x**2
...
>>> square(4)
16

PEP 8 -- Style Guide for Python Code: "Always use a def statement instead of an assignment statement that binds a lambda expression directly to an identifier":

15.8.4. Lambda with Map

Increment:

>>> data = [1, 2, 3, 4]
>>>
>>> result = map(lambda x: x+1, data)
>>> list(result)
[2, 3, 4, 5]

Square:

>>> data = [1, 2, 3, 4]
>>>
>>> result = map(lambda x: x**2, data)
>>> list(result)
[1, 4, 9, 16]

Translate:

>>> PL = {'ą': 'a', 'ć': 'c', 'ę': 'e',
...      'ł': 'l', 'ń': 'n', 'ó': 'o',
...      'ś': 's', 'ż': 'z', 'ź': 'z'}
>>>
>>> text = 'zażółć gęślą jaźń'
>>>
>>> result = map(lambda x: PL.get(x,x), text)
>>> ''.join(result)
'zazolc gesla jazn'

15.8.5. Lambda with Filter

Even numbers:

>>> DATA = [1, 2, 3, 4]
>>>
>>> result = filter(lambda x: x%2==0, DATA)
>>> list(result)
[2, 4]

Adult people:

>>> people = [
...     {'age': 21, 'name': 'Jan Twardowski'},
...     {'age': 25, 'name': 'Mark Watney'},
...     {'age': 18, 'name': 'Melissa Lewis'}]
>>>
>>> result = filter(lambda x: x['age'] >= 21, people)
>>> list(result)  
[{'age': 21, 'name': 'Jan Twardowski'},
 {'age': 25, 'name': 'Mark Watney'}]

Astronauts:

>>> people = [
...     {'is_astronaut': False, 'name': 'Jan Twardowski'},
...     {'is_astronaut': True, 'name': 'Mark Watney'},
...     {'is_astronaut': True, 'name': 'Melissa Lewis'}]
>>>
>>> result = filter(lambda x: x['is_astronaut'], people)
>>> list(result)  
[{'is_astronaut': True, 'name': 'Mark Watney'},
 {'is_astronaut': True, 'name': 'Melissa Lewis'}]
>>> astronauts = ['Mark Watney', 'Melissa Lewis']
>>>
>>> people = ['Jan Twardowski', 'Mark Watney',
...           'Melissa Lewis', 'Jose Jimenez']
>>>
>>> result = filter(lambda x: x in astronauts, people)
>>> list(result)
['Mark Watney', 'Melissa Lewis']

15.8.6. Assignments

Code 15.16. Solution
"""
* Assignment: Function Lambda Chain
* Required: yes
* Complexity: easy
* Lines of code: 2 lines
* Time: 3 min

English:
    1. Inline functions `odd()` and `cube()` with `lambda` expressions
    2. Run doctests - all must succeed

Polish:
    1. Wciel kod `odd()` i `cube()` wykorzystując wyrażenia `lambda`
    2. Uruchom doctesty - wszystkie muszą się powieść

Hints:
    * `mean = sum(...) / len(...)`
    * type cast to `list()` before calculating mean to expand generator

Tests:
    >>> import sys; sys.tracebacklimit = 0

    >>> type(result) is float
    True
    >>> result
    11502.0
"""


def odd(x):
    return x % 2


def cube(x):
    return x ** 3


numbers = (x for x in range(1, 34) if x % 3 == 0)
numbers = filter(odd, numbers)
numbers = map(cube, numbers)
numbers = list(numbers)
result = sum(numbers) / len(numbers)