11.7. Function Lambda¶
Lambda - Anonymous functions
When function is used once
When function is short
You don't need to name it (hence it is anonymous)
>>> lambda x: x+1
<function <lambda> at 0x...>
- lambda¶
Anonymous function
11.7.1. 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
11.7.2. Convention¶
Usually parameters are named
x
andy
Use shortest code possible
Do not assign
lambda
to variableLambda 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":
11.7.3. Note to Programmers of Different Languages¶
query = 'SELECT * FROM users'
result = database(query).stream()
.filter(user -> user.age > 5)
.filter(user -> user.firstname == 'Mark')
.filter((x,y) -> x + y)
.collect(Collectors.toList());
11.7.4. Lambda with Map¶
Increment:
>>> data = [1, 2, 3, 4]
>>>
>>> result = map(lambda x: x+1, data)
>>> list(result)
[2, 3, 4, 5]
11.7.5. Lambda with Filter¶
Even numbers:
>>> DATA = [1, 2, 3, 4]
>>>
>>> result = filter(lambda x: x%2==0, DATA)
>>> list(result)
[2, 4]
11.7.6. Performance¶
>>> %%timeit -r 1000 -n 10_000
... def increment(x):
... return x + 1
... map(increment, range(0,100))
271 ns ± 30.6 ns per loop (mean ± std. dev. of 1000 runs, 10000 loops each)
>>>
>>>
>>> %%timeit -r 1000 -n 10_000
... map(lambda x: x+1, range(0,100))
262 ns ± 29 ns per loop (mean ± std. dev. of 1000 runs, 10000 loops each)
>>> %%timeit -r 1000 -n 1000
... def increment(x):
... return x + 1
... list(map(increment, range(0,100)))
7.48 µs ± 608 ns per loop (mean ± std. dev. of 1000 runs, 1000 loops each)
>>>
>>>
>>> %%timeit -r 1000 -n 1000
... list(map(lambda x: x+1, range(0,100)))
7.36 µs ± 545 ns per loop (mean ± std. dev. of 1000 runs, 1000 loops each)
11.7.7. Use Case - 0x01¶
>>> data = [1, 2, 3, 4]
>>>
>>> result = map(lambda x: x**2, data)
>>> list(result)
[1, 4, 9, 16]
11.7.8. Use Case - 0x02¶
>>> 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'
11.7.9. Use Case - 0x03¶
>>> people = [
... {'age': 21, 'name': 'Mark Watney'},
... {'age': 25, 'name': 'Melissa Lewis'},
... {'age': 18, 'name': 'Rick Martinez'}]
>>>
>>>
>>> result = filter(lambda x: x['age'] >= 21, people)
>>> list(result)
[{'age': 21, 'name': 'Mark Watney'},
{'age': 25, 'name': 'Melissa Lewis'}]
11.7.10. Use Case - 0x04¶
>>> people = [
... {'is_astronaut': False, 'name': 'Mark Watney'},
... {'is_astronaut': True, 'name': 'Melissa Lewis'},
... {'is_astronaut': True, 'name': 'Rick Martinez'}]
>>>
>>>
>>> result = filter(lambda x: x['is_astronaut'], people)
>>> list(result)
[{'is_astronaut': True, 'name': 'Melissa Lewis'},
{'is_astronaut': True, 'name': 'Rick Martinez'}]
11.7.11. Use Case - 0x05¶
>>> astronauts = ['Mark Watney', 'Melissa Lewis']
>>>
>>> people = ['Mark Watney', 'Melissa Lewis',
... 'Rick Martinez', 'Alex Vogel']
>>>
>>>
>>> result = filter(lambda x: x in astronauts, people)
>>> list(result)
['Mark Watney', 'Melissa Lewis']
11.7.12. Assignments¶
"""
* 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 (inline) 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
>>> from inspect import isfunction
>>> assert isfunction(odd), \
'Object `odd` must be a function'
>>> assert isfunction(cube), \
'Object `cube` must be a function'
>>> assert result is not Ellipsis, \
'Assign result to variable: `result`'
>>> assert type(result) is float, \
'Variable `result` has invalid type, should be float'
>>> result
245.0
"""
def odd(x):
return x % 2
def cube(x):
return x ** 3
# Inline lambda expressions
# type: float
result = range(0,10)
result = filter(odd, result)
result = map(cube, result)
result = list(result)
result = sum(result) / len(result)