Lambda функции в Python

 

С помощью ключевого слова lambda в Python можно определять анонимные функции, которые являются объектами функций, аналогично функциям, объявленными с помощью ключевого слова def.

Синтаксис объявления

lambda arguments: expression
arguments - аргументы, expression - выражение, возвращающее значение.

Lambda функции удобно использовать для функций, которые вызываются один раз, а также для функций, которые выполняют одно выражение.

 

Первые примеры

 

Пример lambda функции, которая добавляет к переданному аргументу 1 и возвращает результат:

In [1]:
add_1 = lambda x: x + 1
add_1(8)
Out[1]:
9
 

Видно, что функция начинается со слова lambda, затем через пробел указан параметр функции - x (а могла быть другая буква), затем, после двоеточия, указывается выражение, результат выполнения которого будет возвращен функцией.

Еще пример. Функция складывает два числа, переданных в качестве аргументов:

In [2]:
add_2 = lambda x, y: x + y
add_2(3, 4)
Out[2]:
7
 

А другие буквы вместо параметров? Пожалуйста:

In [3]:
add_2 = lambda f123, er45: f123 + er45
add_2(3, 4) 
Out[3]:
7
 

Все же в приведенных примерах нет анонимности, поскольку происходит присваивание функции переменной.

Приведем пример анонимного вызова функции, которая возвращает результат умножения переданных аргументов. Аргументы передаются в скобках после скобок, содержащих определение lambda функции:

In [4]:
(lambda x, y: x * y)(3, 5)
Out[4]:
15
 

Пример со строками:

In [5]:
(lambda x, y: x * y)("Ха-",3)
Out[5]:
'Ха-Ха-Ха-'
In [6]:
(lambda x, y: x + y)("Первая","Вторая")
Out[6]:
'ПерваяВторая'
 

А вот пример функции, которая игнорирует аргументы:

In [7]:
(lambda x, y: "Ха-ха-ха")(3, 5)
Out[7]:
'Ха-ха-ха'
 

Пример функции без параметров:

In [8]:
(lambda: [0,1,2,3])()
Out[8]:
[0, 1, 2, 3]
 

Параметрам функции можно задать значения по умолчанию.

In [9]:
(lambda x=3, y = 5: x + y)()
Out[9]:
8
 

Или так:

In [10]:
(lambda x, y = 7: x + y)(3)
Out[10]:
10
In [11]:
(lambda x,y=3: x + y)([1,2,3],[3,4,5])
Out[11]:
[1, 2, 3, 3, 4, 5]
In [12]:
(lambda x,y=3: x[0] + y)([1,2,3])
Out[12]:
4
 

Попробуем умножение:

In [13]:
(lambda x=3, y=7: x * y)("Ха-")
Out[13]:
'Ха-Ха-Ха-Ха-Ха-Ха-Ха-'
In [14]:
(lambda x,y=3: x * y)([1,2,3])
Out[14]:
[1, 2, 3, 1, 2, 3, 1, 2, 3]
In [15]:
(lambda x, y = 3: x * y)(["Hello"])
Out[15]:
['Hello', 'Hello', 'Hello']
 

Первые выводы о lambda функции:

  1. Функция всегда возвращает значение, хотя не использует оператор return.
  2. Эта функция одного выражения (тело функции содержит одно выражение).
  3. Функцию можно использовать без назначения имени.
 

Более сложные примеры

 

Возведем в куб каждый элемент списка:

In [16]:
a = [1,3,4,6]
list(map(lambda x: x ** 3, a))
Out[16]:
[1, 27, 64, 216]
 

Отсортируем список чисел по модулю:

In [17]:
a = list(range(-10, 10))
print(f"Сначала список выглядел так {a}.")
 
 Сначала список выглядел так [-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9].
In [18]:
print("Сортируем:")
sorted(a, key=lambda x: x*x)
 
 Сортируем:
Out[18]:
[0, -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7, -8, 8, -9, 9, -10]
 

Или так:

In [19]:
sorted(a, key=lambda x: x if x >= 0 else -x)
Out[19]:
[0, -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7, -8, 8, -9, 9, -10]
 

В последнем примере функция возвращает x, если x больше или равен 0, и -x в других случаях.

Видно, что в выражении можно использовать условный оператор if.

Отсортируем числа так, чтобы впереди были числа, которые делятся на 2 или 3:

In [20]:
l = len(a)/2
sorted(a, key=lambda x: x if (x % 2 == 0) or (x % 3 == 0) else l)
Out[20]:
[-10, -9, -8, -6, -4, -3, -2, 0, 2, 3, 4, 6, 8, 9, -7, -5, -1, 1, 5, 7]
 

Обнулим в списке все числа, не кратные 3

In [21]:
list(map(lambda x: x if x % 3 == 0 else 0, a))
Out[21]:
[0, -9, 0, 0, -6, 0, 0, -3, 0, 0, 0, 0, 0, 3, 0, 0, 6, 0, 0, 9]
 

Лексическое замыкание (lexical closure) с помощью lambda функции

 

Лексическое замыкание - это когда функция запоминает некоторые значения из окружения и может использовать их даже когда поток программы не находится в этом окружении.

In [22]:
def adder(n):
    return lambda x: x + n

add_5 = adder(5)
add_15 = adder(15)
In [23]:
add_5(10)
Out[23]:
15
In [24]:
add_15(10)
Out[24]:
25
 

По сути функция возвращает анонимную функцию, которая и создает магию.

 

Использование lambda функций в классах

 

Тут все просто - не забывайте добавлять первым параметром self, а далее остальные параметры:

In [25]:
class Dog:
    gav = lambda self: print("Gav!!")
    
dog = Dog()
dog.gav()
 
 Gav!!
 

Использование lambda функций с pandas DataFrame. Метод apply

In [26]:
import numpy as np
import pandas as pd
In [27]:
d1 = pd.DataFrame(np.random.randint(low=0, high=10, size=(5, 5)),
                  columns=['a', 'b', 'c', 'd', 'e'])
d1

Out[27]:
  a b c d e
0 9 2 7 4 4
1 9 6 5 4 2
2 5 0 0 8 7
3 8 3 3 5 3
4 4 6 8 7 1
 

Используем метод apply(lambda x:x) для работы с DataFrame.

По умолчанию x - это столбец

In [28]:
d1.apply(lambda x: x)
Out[28]:
  a b c d e
0 9 2 7 4 4
1 9 6 5 4 2
2 5 0 0 8 7
3 8 3 3 5 3
4 4 6 8 7 1
 

Ничего не поменялось, это логично. Посмотрим на каждый x:

In [29]:
d1.apply(lambda x: print(x))
 
0    9
1    9
2    5
3    8
4    4
Name: a, dtype: int64
0    2
1    6
2    0
3    3
4    6
Name: b, dtype: int64
0    7
1    5
2    0
3    3
4    8
Name: c, dtype: int64
0    4
1    4
2    8
3    5
4    7
Name: d, dtype: int64
0    4
1    2
2    7
3    3
4    1
Name: e, dtype: int64
Out[29]:
a    None
b    None
c    None
d    None
e    None
dtype: object
In [30]:
d1.apply(lambda x: print(type(x)))
 
<class 'pandas.core.series.Series'>
<class 'pandas.core.series.Series'>
<class 'pandas.core.series.Series'>
<class 'pandas.core.series.Series'>
<class 'pandas.core.series.Series'>
Out[30]:
a    None
b    None
c    None
d    None
e    None
dtype: object
 

Видно, что каждый x - pandas.Series со значениями столбца. Обратите внимание на выходное значение - каждый столбец заполнился значением None, которое возвращает функция print. Это объясняется просто - в результате применения функции с помощью apply по умолчанию вернется какое-то значение для каждого столбца. Например так:

In [31]:
d1.apply(sum)
Out[31]:
a    35
b    17
c    23
d    28
e    17
dtype: int64
In [32]:
d1.apply(np.mean)
Out[32]:
a    7.0
b    3.4
c    4.6
d    5.6
e    3.4
dtype: float64
 

Зато в следующем примере ответ выглядит иначе:

In [33]:
d1.apply(lambda x: x if x[0]> 5 else -x)
Out[33]:
  a b c d e
0 9 -2 7 -4 -4
1 9 -6 5 -4 -2
2 5 0 0 -8 -7
3 8 -3 3 -5 -3
4 4 -6 8 -7 -1
 

То есть для каждого столбца мы возвращаем этот же столбец, меняя знак, в зависимости от первого элемента в столбце. Поэтому форма сохраняется.

 

А если так:

In [34]:
d1.apply(lambda x: [1,2,3,4])
Out[34]:
a    [1, 2, 3, 4]
b    [1, 2, 3, 4]
c    [1, 2, 3, 4]
d    [1, 2, 3, 4]
e    [1, 2, 3, 4]
dtype: object
 

Однако, ответ в следующем примере, в котором количество элементов в возвращаемом списке равно количеству элементов в столбце, выглядит иначе:

In [35]:
d1.apply(lambda x: [1,2,3,4,5])
Out[35]:
  a b c d e
0 1 1 1 1 1
1 2 2 2 2 2
2 3 3 3 3 3
3 4 4 4 4 4
4 5 5 5 5 5
 

Два других выражения эквивалентны:

In [36]:
d1.apply(lambda x: x*3)
Out[36]:
  a b c d e
0 27 6 21 12 12
1 27 18 15 12 6
2 15 0 0 24 21
3 24 9 9 15 9
4 12 18 24 21 3
 
In [37]:
d1*3
Out[37]:
  a b c d e
0 27 6 21 12 12
1 27 18 15 12 6
2 15 0 0 24 21
3 24 9 9 15 9
4 12 18 24 21 3
 

Следующее выражение расширяет список на элементы DataFrame

In [38]:
d1.apply(lambda x: [1,2,3,4], result_type='expand')
Out[38]:
  a b c d e
0 1 1 1 1 1
1 2 2 2 2 2
2 3 3 3 3 3
3 4 4 4 4 4
 

Работаем со строками (axis=1). Напомним данные:

In [39]:
d1
Out[39]:
  a b c d e
0 9 2 7 4 4
1 9 6 5 4 2
2 5 0 0 8 7
3 8 3 3 5 3
4 4 6 8 7 1
In [40]:
d1.apply(lambda x: print(x), axis=1)
 
a    9
b    2
c    7
d    4
e    4
Name: 0, dtype: int64
a    9
b    6
c    5
d    4
e    2
Name: 1, dtype: int64
a    5
b    0
c    0
d    8
e    7
Name: 2, dtype: int64
a    8
b    3
c    3
d    5
e    3
Name: 3, dtype: int64
a    4
b    6
c    8
d    7
e    1
Name: 4, dtype: int64
Out[40]:
0    None
1    None
2    None
3    None
4    None
dtype: object
In [41]:
d1.apply(sum, axis=1)
Out[41]:
0    26
1    26
2    20
3    22
4    26
dtype: int64
In [42]:
d1.apply(np.mean, axis=1)
Out[42]:
0    5.2
1    5.2
2    4.0
3    4.4
4    5.2
dtype: float64
In [43]:
d1.apply(lambda x: [1,2,3,4,5], axis=1)
Out[43]:
0    [1, 2, 3, 4, 5]
1    [1, 2, 3, 4, 5]
2    [1, 2, 3, 4, 5]
3    [1, 2, 3, 4, 5]
4    [1, 2, 3, 4, 5]
dtype: object
 

Видно, что расширения автоматически не происходит

In [44]:
d1.apply(lambda x: [1,2,3,4,5], axis=1, result_type='expand')
Out[44]:
  0 1 2 3 4
0 1 2 3 4 5
1 1 2 3 4 5
2 1 2 3 4 5
3 1 2 3 4 5
4 1 2 3 4 5
 

И в конце - способ полностью заменить DataFrame

In [45]:
d1.apply(lambda x: pd.Series([1, 2], index=['foo', 'bar']), axis=1)
Out[45]:
  foo bar
0 1 2
1 1 2
2 1 2
3 1 2
4 1 2
In [46]:
d1.apply(lambda x: pd.Series([1, 2], index=['foo', 'bar']))
Out[46]:
  a b c d e
foo 1 1 1 1 1
bar 2 2 2 2 2
 

Пока все.

Установка Linux Debian в VirtualBox

Установка VirtualBox

Тут все просто.

Скачиваем VirtualBox со страницы разработчика.

Запускаем установку и, в процессе установки, со всем соглашаемся.

Получение образа Debian

Идем на сайт https://www.debian.org/distrib/, выбираем небольшой установочный образ. В нашем случае выбираем iso-образы netinst для 64-битных ПК.

clip_image008

Пока образ качается, создаем новую виртуальную машину в VirtualBox.

Создание виртуальной машины

Перед созданием виртуальной машины необходимо включить в BIOS виртуализацию на вашем ПК (если она поддерживается). Иначе вам не удастся создать 64-битную виртуальную машину.

Запускаем VirtualBox.

После успешного запуска нажимаем кнопку “Создать”, вводим имя машины и пр.

clip_image001

В следующем диалоге задаем размер памяти для виртуальной машины.

clip_image002

Размер памяти можно потом изменить.

Далее создаем виртуальный жесткий диск. 

clip_image003

clip_image004

Нам важно создать “Фиксированный виртуальный жесткий диск” для повышения быстродействия виртуальной машины. Поэтому нажимаем кнопку «Скрыть подробности» (это такой перевод – возможно в вашей версии будет “Показать подробности”).

clip_image005

Установим переключатель в положение “Фиксированный виртуальный жесткий диск” и нажмем кнопку “Создать”.

clip_image006

Пока машина создается, у нас загрузился iso с Debian.

clip_image010

Все готово к установке.

Установка Debian

Запускаем Virtualbox, (если вы его уже закрыли) переходим на запись DebianTest (созданную по выше описанным инструкциям) и нажимаем кнопку «Настроить».

clip_image012

Переходим на вкладку «Носители». Выбираем «Контролер: IDE \ Пусто». Затем выбираем кнопку рядом с кнопкой «Вторичный мастер IDE».

clip_image014

clip_image016

Выбираем скачанный файл в качестве образа.

Все готово для установки.

Запускаем виртуальную машину.

Далее идут подряд экраны с небольшими комментариями.

Первый экран.

clip_image017

Выбираем Install, нажимаем Enter.

На следующем экране выбираем язык, который будет использоваться в процессе установки. Подтверждаем выбор клавишей Enter.

clip_image019

Выбираем язык Russian.

Затем выбираем местоположение и пр.

clip_image021

clip_image023

clip_image025

Производится загрузка дополнительных компонентов, определение оборудования.

Затем снова диалоги.

clip_image027

clip_image029

clip_image031

clip_image033

clip_image035

clip_image037

clip_image039

clip_image041

clip_image043

Далее загружаются дополнительные компоненты (пару секунд) .

И вот важный момент – разбиение диска. Нам нужно разбить его на два первичных раздела: раздел подкачки (0.5 Гбайт) и корневой раздел  (точка монтирования – "/");

Поэтому на следующем экране выбираем “Вручную”. Далее по картинкам.

clip_image045

Выбираем наш диск

clip_image047

clip_image049

clip_image051

clip_image053

clip_image055

clip_image057

clip_image059

В следующем экране нужно нажать “Enter” для смены типа файловой системы диска.

clip_image061

clip_image063

clip_image065

clip_image067

clip_image069

clip_image071

clip_image073

clip_image075

clip_image077

clip_image079

clip_image081

Далее идет установка базовой системы.

clip_image083

Выбираем источник дистрибутивов.

clip_image085

clip_image087

clip_image089

Поехали.

clip_image091

Важный запрос.

clip_image093

Добрались до главного – что мы хотим установить.

clip_image095

Далее самый длительный процесс установки ПО.

………………………………….

После этого запрос об установке загрузчика.

clip_image097

Еще чуть-чуть и…

clip_image099

Перегружаем и видим запрос на регистрацию пользователя.

clip_image101

Все, система установлена, софт VirtualBox «Дополнения для гостевой ОС» ставить не надо, все уже работает.

Внимание! Сайт не собирает, не обрабатывает и не хранит персональные данные пользователей!
На устройстве пользователя могут сохраняться временные файлы cookie, которые не содержат персональные данные и обеспечивают комфортную работу пользователя с сайтом. Продолжение работы с сайтом означает ваше согласие на использование файлов cookie