Наталья Кайда 16 января 2023

🐍 Самоучитель по Python для начинающих. Часть 12: Анонимные функции

Изучаем особенности лямбда-функций в Python: разбираемся, когда стоит использовать анонимные функции вместо обычных, и в каких случаях lambda-выражения лучше заменить списковыми включениями. В конце статьи – 10 практических заданий с решениями.
🐍 Самоучитель по Python для начинающих. Часть 12: Анонимные функции

Происхождение названия

Лямбда-функции часто называют анонимными потому, что такую функцию можно определить с помощью оператора lambda, не давая ей название. Происхождение термина «лямбда» связано с формальной системой λ-исчисления.

Назначение и особенности анонимных функций в Python

1. Лямбда-функции используются в качестве краткого способа определения обычных def функций. Например, так будет выглядеть стандартная функция для вычисления дискриминанта:

        def discr(b, a, c):
    return b ** 2 - 4 * a * c

    

А так – анонимная:

        lambda b, a, c: b ** 2 - 4 * a * c
    

2. Анонимные функции используются однократно, в том участке кода, где были определены. Если функцию нужно вызывать многократно, следует написать обычную функцию def. Чаще всего анонимные функции используют совместно со встроенными функциями map(), filter(), sorted(), min(), max() и т. п. Особенно удобно применять лямбда-функции для сортировки:

        mydict = {'слива':5, 'папайя':6, 'лук':56, 'маракуйя':78, 'ежевика':45}

print('До сортировки: ', mydict)
sorted_mydict = dict(sorted(mydict.items(), key=lambda item: len(item[0])))
print('После сортировки: ', sorted_mydict)

    

Вывод:

        До сортировки:  {'слива': 5, 'папайя': 6, 'лук': 56, 'маракуйя': 78, 'ежевика': 45}
После сортировки:  {'лук': 56, 'слива': 5, 'папайя': 6, 'ежевика': 45, 'маракуйя': 78}

    
🐍 Библиотека питониста
Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека питониста»
🐍🎓 Библиотека собеса по Python
Подтянуть свои знания по Python вы можете на нашем телеграм-канале «Библиотека собеса по Python»
🐍🧩 Библиотека задач по Python
Интересные задачи по Python для практики можно найти на нашем телеграм-канале «Библиотека задач по Python»

3. Присваивание лямбда-функциям имен не приводит к ошибке, но считается плохой практикой в соответствии с рекомендациями PEP8, поскольку противоречит самой концепции анонимности: такие функции используются однократно, и поэтому имена им не нужны:

        #Можно, но не нужно
max_num = lambda a, b : a if a > b else b

#Правильно
def max_num(a, b):
    return a if a > b else b 

    

4. Анонимные функции вызываются сразу после определения. Здесь лямбда-функция выполняет сортировку списка словарей по возрастанию цены:

        fruit = [
    {'название':'виноград',
     'цена': 230,
     'количество': 412
    },
    {'название':'манго',
     'цена': 350,
     'количество': 21
    },
    {'название':'бананы',
     'цена': 70,
     'количество': 234
    },
    {'название':'яблоки',
     'цена': 66,
     'количество': 213
    },
    ]
print(sorted(fruit, key=lambda item: item['цена']))

    

Вывод:

        [{'название': 'яблоки', 'цена': 66, 'количество': 213}, {'название': 'бананы', 'цена': 70, 'количество': 234}, {'название': 'виноград', 'цена': 230, 'количество': 412}, {'название': 'манго', 'цена': 350, 'количество': 21}]
    

5. Анонимные функции могут принимать неограниченное количество аргументов, но не могут содержать более одного выражения. Если в определении лямбда-функции записать два и более выражений, интерпретатор вернет ошибку:

        lambda a : a + 10, a - 5
    

Сообщение об ошибке:

        NameError: name 'a' is not defined
    

6. Лямбда-функции можно включать в тело обычных функций. Эта функция будет удваивать все получаемые значения:

        def my_function(n):
  return lambda a : a * n
double = my_function(2)
print(double(15))

# Вывод:
30
    

7. В анонимных функциях можно использовать условия и операторы сравнения. Здесь анонимная функция добавляет слово гласная или согласная в список в зависимости от того, является ли буква в строке st гласной или согласной:

        st = 'яжертыуиопшщасдфгчйклзхцвбнм'
vowels = 'аиеёоуыэюя'
result = list(map(lambda x: 'гласная' if x in vowels else 'согласная', st))
print(result)

    

Вывод:

        ['гласная', 'согласная', 'гласная', 'согласная', 'согласная', 'гласная', 'гласная', 'гласная', 'гласная', 'согласная', 'согласная', 'согласная', 'гласная', 'согласная', 'согласная', 'согласная', 'согласная', 'согласная', 'согласная', 'согласная', 'согласная', 'согласная', 'согласная', 'согласная', 'согласная', 'согласная', 'согласная', 'согласная']
    

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

        numbers = [7, 8, 6, 9, 4, -6, 2, 0, -3, -12, -5, -2, 12, 77, 32]
print(list(filter(lambda x: x > 6 and x % 2 == 0, numbers)))

    

8. Анонимные функции являются замыканиями – им доступны внешние переменные. В этом примере внутренняя лямбда-функция принимает список и возвращает минимальный или максимальный элемент в зависимости от соответствующего параметра внешней функции:

        def get_min_or_max(value='max'):
    return eval(f'lambda x: {value}(x)')
 
lst = [3, 5, -22, -15, 100, 7, 8, 9, 12, 98]
 
max_func = get_min_or_max()
min_func = get_min_or_max('min')
print(max_func(lst))
print(min_func(lst))

    

Вывод:

        100
-22

    

9. В отличие от обычных функций, анонимные не могут содержать return, pass, assert и raise.

10. Подобно обычным функциям, лямбда-выражения поддерживают различные типы аргументов:

  • позиционные;
  • именованные;
  • смешанные (позиционные + именованные);
  • *args;
  • **kwargs.

11. Лямбда-функции для проведения последовательных операций можно хранить в списках:

        ops = [(lambda x, y: x + y), (lambda x, y: x - y),
       (lambda x, y: x * y), (lambda x, y: x / y)]

x, y = int(input()), int(input())
for i in range(len(ops)):
    print(ops[i](x, y))

# Пример вывода для x = 12, y = 15:
27
-3
180
0.8
    

А также в словарях:

        ops = {'neg': lambda x: abs(x), 'pos': lambda x: x / 2, 'zero': lambda x: x + 5}
lst = list(map(int, input().split()))
for i in lst:
    if i < 0:
        print(ops['neg'](i))
    elif i > 0:
        print(ops['pos'](i))
    else:
        print(ops['zero'](i))

# Пример вывода для 4 -5 0 6 -3:
2.0
5
5
3.0
3

    

12. Во многих случаях лямбда-функции можно заменить списковыми включениями. К примеру, здесь анонимная функция используется для возведения элементов списка в куб:

        my_list = [3, 5, 6, 7, 2, 8, 9, 10]
cubes = map(lambda x: pow(x, 3), my_list) # или x ** 3
print(list(cubes))

    

Однако тот же результат можно получить проще:

        print([i ** 3 for i in my_list])



    

Вывод:

        [27, 125, 216, 343, 8, 512, 729, 1000]
    

А здесь лямбда-функция используется для выбора четных чисел из списка:

        my_list = [4, 2, 3, 5, 16, 12, 2, 8, 9, 10]
print(list(filter(lambda x: x % 2 == 0, my_list)))

    

Вывод:

        [4, 2, 16, 12, 2, 8, 10]
    

Точно такой же результат даст простое списковое включение:

        print([i for i in my_list if i % 2 == 0])
    

Очень часто лямбда-функции используются совместно с filter():

        lst = ['ролл', 'яблоко', 'книга', 'шар', 'ноутбук']

print(list(filter(lambda x: len(x) > 4, lst)) )
print(list(filter(lambda x: 'р' in x, lst)))

    

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

        print([i for i in lst if len(i) > 4])
print([i for i in lst if 'р' in i])

    

Вывод:

        ['яблоко', 'книга', 'ноутбук']
['ролл', 'шар']

    
***

Отлично! Вы полностью изучили теорию анонимных lambda-функций.

Теперь вы знаете всё об их синтаксисе, 12 ключевых особенностях и даже о том, когда их лучше заменять более читаемыми конструкциями. У вас есть вся необходимая теоретическая база.

Но теория — это лишь половина пути. Чтобы по-настоящему овладеть этим мощным инструментом, нужна практика. В полной версии урока вас ждут:

  • 10 практических задач: Вы научитесь применять лямбда-функции для решения реальных проблем — от продвинутой сортировки словарей и анализа данных до элегантных алгоритмических вычислений.
  • Закрепление навыков: Вы на деле убедитесь, как лямбды в одну строку заменяют громоздкие циклы и делают код лаконичнее.

Комментарии

ВАКАНСИИ

Добавить вакансию
Lead C++ Software Engineer (Gameplay)
по итогам собеседования
AppSec BP
по итогам собеседования

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ