Skip to content

Instantly share code, notes, and snippets.

@Beastrock
Last active July 26, 2017 00:17
Show Gist options
  • Save Beastrock/634b7b0f2d308a88c0b4448c54edf724 to your computer and use it in GitHub Desktop.
Save Beastrock/634b7b0f2d308a88c0b4448c54edf724 to your computer and use it in GitHub Desktop.
Lambda functions. [For devman.org Q and A]
>Объясните на пальцах как они работают, перечитал кучу информации, но так и не могу понять глобально как они работают
# О ней..
Для начала небольшое резюмэ.
****Lambda-функция**** - [анонимная функция](https://ru.wikipedia.org/wiki/%D0%90%D0%BD%D0%BE%D0%BD%D0%B8%D0%BC%D0%BD%D0%B0%D1%8F_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D1%8F), простым неуглубляющимся в сорцы языком кэпа, функция не имеющая имени.
Наглядный пример отличия обычной функция от lambda можно увидеть, поигравшись с интерпретатором:
```python
>>> def normal_func(a):
... return a + 1
>>> lambda_func = lambda a: a + 1
```
Вызывается она также как и обычная функция:
```python
>>> normal_func(1)
2
>>> lambda_func(1)
2
```
По типу от обычной не отличается:
```python
>>> type(normal_func)
<type 'function'>
>>> type(lambda_func)
<type 'function'>
```
Но, если мы вызовем magic-method `__name__`, который возвращает имя функции, то увидим разницу:
```python
>>> normal_func.__name__
'normal_func'
>>> lambda_func.__name__
'<lambda>'
```
Имя у неё всё таки есть, как видите :)
А смысл конструкции простой, она ведет себя так:
```\
def lambda(<аргумент(ы) на вход>):
# тело функции отсутствует
return <выражение, которая функция возвращает>
```
А записывается, как мы помним, так:
```
<lambda>(<аргумент(ы) на вход>): <выражение, которая функция возвращает>
```
За `<выражение, которая функция возвращает>` может скрываться многое:
```python
>>> lambda x: int(x) #конвертация значения в int
>>> lambda x, y, z: x > y > z # cравнение интервала значений
>>> lambda x: x['key'] # взятие ключа из словаря
```
# Зачем?
Вы бы стали объявлять переменную ради её одноразового использования?
Например в нашей `normal_func`:
```python
# Why?
def normal_func(a):
incremented_value = a + 1
return incremented_value
# Ok
def normal_func(a):
return a + 1
```
Это нерационально. Вот по той же причине нерационально объявлять и функцию для одноразовой работёнки, когда можно обойтись короткой записью с lambda. Также небольшим плюсом lambda является её быстрота по сравнению с обычной функцией.
# Combination is the answer. Usage examples.
Как в Linux каждая команда делает качественно что-то одно, но при этом в множественной комбинации с другими командами образует сильный упрощающий жизнь инструмент, так и lambda функция синергирует с некоторыми [питоновскими built-in функциями]('https://docs.python.org/3.5/library/functions.html').
Начнём с простого.
* `sorted()`, `sort()`, `max()` и `min()` - здесь lambda-функция выступает ключем, по которуму сортируется итерируемый объект(список, словарь и др.), берется максимальное или минимальное значение из него. Рассмотрим пример:
```python
>>> a = ['Съешь','ещё','этих','мягких','французких','булочек']
>>> sorted(a, key=lambda x: len(x))
['ещё', 'этих', 'Съешь', 'мягких', 'булочек', 'французких']
```
Список сортируется по тем значениям, которые получились в результате преобразования lambda-функцией. Такой финт может пригодиться в первых задачах. Как видите lambd'e можно смело передать на выход любую команду. Ссылка на [мини гайд по сортировке](https://wiki.python.org/moin/HowTo/Sorting).
<hr>
Три танкиста - три весёлых друга: `filter`, `map` и `lambda`.
* `map(function, iterable, ...)` - принимает итерируемый объект(список, словарь и др.) и также приНимает на вход функцию, которая затем, приМеняется ко всем элементам. Сама функция возвращает итератор по новому получившемуся списку.
```python
>>> simple_list = [1, 2, 3, 4, 5, 6, 7, 8]
>>> squares = map(lambda x: x**2, simple_list)
>>> list(squares)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
```
* `filter(function, iterable)` - принимает на вход функцию, которая возвращает True/False и итерируемый объект(список, словарь и др.). Сама функция возвращает список со значениями, которые в результате применения lambda-функции возвратили True.
```python
>>> simple_list = [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4]
>>>
>>> list( filter((lambda x: x < 0), simple_list))
[-5, -4, -3, -2, -1]
>>>
```
<hr>
## Создание функций
Код ниже определяет функцию "make_incrementor", которая создаёт анонимную функцию и возвращает её. Возвращаемая функция и есть старая добрая normal_func из первого примера. Она прибавляет переданное ей значение к значению, которое уже было задано в аргументе "make_incrementor" при создании.
Можно насоздавать разных прибавляшек и присвоить им переменным. Это идея без lamda-функции выглядела бы не так лаконично. Другое дело нужно ли нам инкременторы эти или нет? =) Но как пример использования имеет место быть.
```python
>>> def make_incrementor (n): return lambda x: x + n
>>>
>>> f = make_incrementor(2)
>>> g = make_incrementor(6)
>>>
>>> f(42), g(42)
(44, 48)
>>>
>>> make_incrementor(22)(33)
55
```
<hr>
Много других примеров использования можно найти в этой [статье](http://www.bogotobogo.com/python/python_functions_lambda.php). Пруф быстродействия lamda и ещё одно множество примеров [здесь](http://www.bogotobogo.com/python/python_functions_lambda.php).
Также стоит помнить, что альтернативой filter- и map-функций являются list comprehensions, но это уже другая история. =)
```python
map(lambda x: x**2, range(5)) VS [x**2 for x in range(5)]
filter(lambda x: x.attribute == value, my_list) VS [x for x in my_list if x.attribute == value]
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment