{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Python для сбора данных\n", "\n", "*Алла Тамбовцева, НИУ ВШЭ*\n", "\n", "## Lambda-функции" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Lambda-функции в Python\n", "\n", "Иногда возникает необходимость написать небольшую функцию, которая будет использоваться один раз, да и то в сочетании с какими-нибудь другими функциями или методами. В таком случае совсем необязательно создавать эту функцию с помощью `def` и присваивать ей имя. Можно воспользоваться специальными lambda-функциями, которые создаются в одну строчку и могут существовать без имени (их ещё назвают *анонимными*).\n", "\n", "Для начала создадим какую-нибудь не-анонимную функцию, чтобы познакомиться с синтаксисом. Пусть это будет функция `sq`, которая принимает на вход какое-то число `x` и возвращает его квадрат." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "sq = lambda x: x ** 2 # готово" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Использовать эту функцию можно как функции, заданные через `def`:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "100" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sq(10)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "49" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sq(-7)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Если функция принимает на вход более одного аргумента, они просто перечисляются через запятую после `lambda`:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "my_sum = lambda x, y: x + y" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "7" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_sum(0, 7)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "13" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "my_sum(6, 7)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Теперь посмотрим на сочетание lambda-функций с встроенными функциями Python. Lambda-функции часто используют в сочетании с функциями `filter()` и `map()`, которые позволяют отфильтровывать значения списков/кортежей или преобразовывать их элементы (более быстрая и удобная альтернатива списковым включениям).\n", "Если вы помните, когда мы обсуждали списки, мы говорили про метод `.index()`, который возвращает индекс какого-то элемента по его значению. Проблема в том, что в случае списка с повторяющимися значениями он возвращает только первое совпадение:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "L = [0, 2, 7, 5, 4, 3, 2]\n", "L.index(2) # только первая 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Если мы захотим таким образом вернуть все элементы, удовлетворяющие некоторому условию, ничего не получится (понадобятся циклы, условия, списковые включения). А можно просто написать lambda-функцию, которая будет возвращать значения True или False в зависимости от соответствия условию, а потом передать полученный результат функции `filter()`, которая отберет элементы с True: " ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[7, 5, 4]" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(filter(lambda x: x > 3, L)) # элементы списка L больше 3" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 2, 4, 2]" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(filter(lambda x: x % 2 == 0, L)) # четные элементы списка L" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Условия можно совмещать:" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[5, 4]" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(filter(lambda x: (x > 3) & (x < 7), L)) # 3 < x < 7" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Обратите внимание: перед `filter()` всегда добавляется `list()`. Это нужно для того, чтобы увидеть результаты явно и получить их в виде списка. Иначе мы просто получим «закрытый» объект типа `filter()` ( вспомните историю про `zip()`)." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "filter(lambda x: x > 3, L)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Теперь попробуем совместить lambda-функцию и функцию `map()`, которая позволяет получать новый список на основе старого, преобразовывая его элементы:" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 4, 49, 25, 16, 9, 4]" ] }, "execution_count": 50, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(map(lambda x: x ** 2, L)) # квадраты элементов списка L" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.8" } }, "nbformat": 4, "nbformat_minor": 1 }