Функции в Python
В предыдущих разделах мы уже часто сталкивались с встроенными функция ( int, float, print, type, len ) Каждая функция в Python предназначена для выполнения одной конкретной задачи. Использование функции упрощает написание и чтение кода.
Содержание страницы: |
---|
1. Функция в Python |
2. Передача аргументов функции |
2.1 Позиционные аргументы |
2.2. Именованные аргументы |
2.3. Значения по умолчанию |
2.4. Передача произвольного набора аргументов |
2.5. Позиционные аргументы с произвольным набором аргументов |
2.6. Произвольный набор именнованных аргументов |
3. Возвращаемое значение в функции |
3.1. Возвращение простого значения |
3.2. Возвращение словаря |
4. Использования функции в цикле while |
5. Передача списка функции на Python |
6. Использование лямбда-выражений вместо функций |
1. Функция в Python
Если какая то задача выполняется многократно в программе, то не обязательно эту задачу расписывать во всех разделах программы, достаточно поместить код в функцию и в последующем вызывать эту функцию по мере необходимости.
Напишем функцию, которая вычисляет квадрат своего аргумента и выводит на экран:
>>> def square ( number ):
. """Вычисление квадрата числа"""
. print(number ** 2)
.
>>> square (5)
25
>>> square (124.45)
15487.802500000002
Определение функции начинается с ключевого слова def , за которым следует имя функции — square . Имя функции, как и имена переменных рекомендуется писать с букв нижнего регистра, а в именах, состоящих из нескольких слов, составляющие должны разделяться символами подчеркивания. Далее в круглых скобках записываются параметры (аргументы) функции, разделенные запятыми. Функция square имеет только один аргумент с именем number — значение, возводимое в квадрат. В случае отсутствия параметров у функции пустые круглые скобки обязательны. В конце строки за параметрами всегда ставится двоеточие ( : ).
После двоеточия новая строка должна идти с отступом (4 пробела). Все строки с отступом образуют тело или блок функции. В "Руководстве по стилю кода Python" указано, что первой строкой блока функции должна быть doc-строка, кратко поясняющая назначение функции: """Вычисление квадрата числа""" . Сам код в теле функции состоит всего из одной строки print(number ** 2).
Команда squre(5) вызывает функции square() и передает ей значение аргумента, для выполнения команды print. Функция возводит число в квадрат и выводит на экран.
2. Передача аргументов функции в Python
2.1. Позиционные аргументы
Функция может иметь несколько параметров и при её вызове должно передаваться сразу несколько аргументов. Напишем функцию, которая выводит название автомобиля, модель и его пробег:
>>> def car (car_brend, car_model, mileage):
. """Выводит информацию о автомобиле"""
. print(f"Продается
.
>>> car ('bmw', 'x5', 51345)
Продается Bmw X5 с пробегом 51345 км.
В данной функции видно, что должно передаваться три аргумента название автомобиля ( car_brend), модель (car_model) и пробег (mileage) . При вызове функции мы должны передать аргументы именно в том порядке, в каком они сохраняются в функции. Если нарушить порядок следования аргументов, то при вызове возможны неожиданные результаты или ошибки.
2.2. Именованные аргументы
Если порядок передачи аргументов по каким то причинам не известен, то можно использовать именованные аргументы. Именованный аргумент представляет собой пару "имя-значение". Имя и значения связываются с аргументом напрямую, так что при передаче аргумента путаница исключается. Вызовем туже самую функцию car() с помощью именованных аргументов:
>>> def car (car_brend, car_model, mileage):
. """Выводит информацию о автомобиле"""
. print(f"Продается
.
>>> car (mileage = 45152, car_model = 'x5', car_brend='bmw')
Продается Bmw X5 с пробегом 45152 км.
При обработке вызова функции Python знает к какому аргументу принадлежат данные и проблем с выводом не случается.
2.3. Значения по умолчанию
Для каждого параметра функции можно определить значение по умолчанию. Если при вызове функции не был передан аргумент, то используется значение по умолчанию. Все значение по умолчанию всегда должны следовать после параметров, у которых значений по умолчанию нет. Приведем пример той же функции, но тип автомобиля будем использовать по умолчанию
>>> car ('m5' , 56148)
Продается Bmv M5 с пробегом 56148 км.
Для изменения значения по умолчанию, мы можем передать именованный аргумент для изменения значения car_brend='audi':
>>> car ('q7', 35600, car_brend='audi')
Продается Audi Q7 с пробегом 35600 км.
Так как аргумент для параметра car_brend задан явно, Python игнорирует значение по умолчанию.
2.4. Передача произвольного набора аргументов
Иногда заранее не известно сколько аргументов должно быть передано функции, Python позволяет получить произвольное количество аргументов из вызывающей команды. Рассмотрим функцию, которая просто передает любое количество аргументов, к примеру название автомобилей:
Звездочка в имени параметра args приказывает создать Python пустой кортеж с именем args и упаковать в него все полученные результаты и с помощью команды print вывести на экран. В примере видно, что функция работает и при передаче четырех и при передаче одного аргумента.
Для более удобной работы с данными, например изменения регистра символов можно воспользоваться циклом for:
2.5. Позиционные аргументы с произвольным набором аргументов
В случае, когда в функции есть позиционные аргументы и произвольные, параметр получения произвольного количества аргументов должен стоять на последнем месте. Python сначала подберет соответствия для позиционных и именных аргументов, а потом объединит все остальные аргументы в последний параметр colors:
В результате данная функция получает два позиционных аргумента car_brend и car_model, а остальные сохраняются в кортеже colors.
В большинстве программ часто используется имя обобщенного параметра *args для хранения произвольного набора позиционных аргументов.
2.6. Произвольный набор именованных аргументов
Иногда может потребоваться, чтобы функция получала произвольное количество именованных аргументов. В таком случае можно написать функцию, которая получает столько пар "ключ-значение", сколько указано в команде вызова. Например, для построение пользовательских профилей, заранее не известно, какую точно информацию предоставит пользователь. Поэтому определим в функции обязательное предоставление имени и фамилии, а остальная информация может быть получена с помощью произвольного количества именованных аргументов:
>>> def profile (first, last, **user_info):
. """Возвращает словарь с данными о пользователе"""
. user_info['first_name'] = first
. user_info['last_name'] = last
. return user_info
.
>>> profile_1 = profile ('tomas', 'edisson', location='usa')
>>> print(profile_1)
Функция profile ожидает получить имя и фамилию пользователя, а также позволяет передать любое количество пар "имя — значение". Две звездочки в параметре **user_info заставляют Python создать пустой словарь с именем user_info и добавить в него все полученные пары "имя — значение". В теле функции сразу добавляются имя и фамилия, а остальные пары в зависимости от переданных параметров при вызове фукции. В конце словарь возвращается с помощью команды return .
В программах часто используется имя обобщенного параметра **kwargs для хранения произвольного набора ключевых аргументов.
3. Возвращаемое значение в функции на Python
Вместо вывода результата работы напрямую, функция может обработать данные и вернуть значение c помощью команды return . Значение, возвращаемое функцией, называется возвращаемым значением.
3.1. Возвращение простого значения
Напишем функцию, которая возвращает отформатированное имя и фамилию
>>> def form_name (last_name, first_name, middle_name):
. """Возвращает отформатированное полное имя"""
. full_name = f"
. return full_name.title()
.
>>> poet = form_name ('пушкин', 'александр', 'сергеевич')
>>> print(poet)
Пушкин Александр Сергеевич
Функция form_name получает в параметрах имя, фамилию и отечество, далее объединяет эти имена и сохраняет их в переменной full_name. Завершив выполнение, функция возвращает управление в точку вызова с помощью команды return , то есть в строку кода, которая вызывала функцию.
Предположим, что мы не знаем отчество человека, для передачи его фукции параметру middle_name. В связи с этим удобно заранее сделать в функции необязательный аргумент . Присвоим ( middle_name = "" ) пустое значение.
>>> def form_name (last_name, first_name, middle_name=''):
. """Возвращает отформатированное полное имя"""
. full_name = f"
. return full_name.title()
.
>>> poet = form_name ('пушкин', 'александр')
>>> print(poet)
Пушкин Александр
>>> poet = form_name('пушкин', 'александр', 'сергеевич')
>>> print(poet)
Пушкин Александр Сергеевич
С необязательным аргументом мы не получим ошибку (TypeError: form_name() missing 1 required positional argument: 'middle_name') в случае отсутствия на входе данных по аргументу.
3.2. Возвращение словаря
Функция может возвращать и более сложную структуру данных, например словарь или список. Напишем функцию, которая будет возвращать словарь, представляющий человека:
При вызове функции info_person получает имя и фамилию на входе и помещает их сразу в словарь, с ключами имя и фамилия. Затем с помощью команды return возвращает словарь. В будущем со словарем будет удобнее работать, мы сможем отдельно использовать имя, фамилию или другие аргументы функции.
4. Использования функции в цикле while
Функции могут вызываться в циклах while где угодно. Приведем пример цикла while, где у посетителя запрашивают имя и фамилию, а с помощью функции form_name возвращается отформатированное имя и фамилия с приветствием:
def form_name (first_name, last_name):
"""Возвращает отформатированное полное имя"""
full_name = f"
return full_name.title()
while True:
print("\nВведите 'x' если хотите завершить программу")
first_name = input("Введите ваше имя: ")
if first_name == 'x':
break
last_name = input("Введите вашу фамилию: ")
if last_name == 'x':
break
formatted_name = form_name (first_name, last_name)
print(f"\nДобрый день
В данном примере в цикле whle запрашивается имя и фамилия и с помощью функции form_name возвращается отформатированное полное имя и записывается в переменную formatted_name. А затем уже с помощью функции print данные выводятся на экран.
5. Передача списка функции на Python
При передаче аргумента функции мы можем сразу передать список. В результате функция получает доступ сразу ко всему его содержимому. Воспользуемся функцией square которую писали в первом разделе, которая выводит квадрат своего аргумента и немного обновим ее. Но в качестве аргумента мы передадим сразу список чисел, которые нужно обработать и возвести в квадрат.
>>> def square (numbers):
. """Вычисление квадрата числа"""
. for number in numbers:
. print(number ** 2)
.
>>> numbers = [1, 5, 6, 15, -7, 1.5]
>>> square (numbers)
1
25
36
225
49
2.25
В результате функции square мы передаем список numbers. Для возведения всех чисел в квадрат, вначале нам нужно перебрать данный список с помощью цикла for, а затем каждое число возвести в квадрат.
6. Использование лямбда-выражений вместо функций
Для простых функций, например square, который просто вычисляют квадрат числа, можно использовать лямбда-выражения.
>>> square = lambda x : x ** 2
>>> print(square(5))
25
В начале создается переменная square и в дальнейшем по имени переменной будет вызываться лямбда-выражение. Лямбда-выражение является анонимной функцией, то есть функцией, не имеющей имени. Лямбда-выражение начинается с ключевого слова lambda , за которым следует разделенный запятыми список параметров. В нашем примере параметр один x. Затем ставится двоеточие и само выражение x ** 2. В результате при вызове переменной square мы передаем параметр число 5, и оно возводится в квадрат.
Лямбда-выражение может иметь и несколько параметров. Например, перемножать передаваемые числа.
>>> mult = lambda x, y, z : x * y * z
>>> print(mult(2, 4, 6))
48
Таким образом любая простая функция в форме
может быть выражена в более компактной форме посредством лямбда-выражения
Функции Python 3 — Краткая шпаргалка
Функции – главный и самый важный способ организации и повторного использования кода в Python. Функций не может быть слишком много. 1 функция — это блок кода, который используется для выполнения одного связанного действия.
В Python есть два инструмента для создания функций: def и lambda .
Сначала рассмотрим def. К lambda функции вернемся позже.
Python предоставляет вам множество встроенных функций, таких как print() и т.д., но вы также можете создавать свои собственные функции. Эти функции называются пользовательскими функциями.
Объявление функции начинается ключевым словом def, а результат возвращается в предложении return:
Ничто не мешает иметь в функции несколько предложений return. Если при выполнении достигнут конец функции, а предложение return не встретилось, то возвращается None.
У функции могут быть позиционные и именованные аргументы.
Именованные аргументы обычно используются для задания значений по умолчанию и необязательных аргументов.
- x и y – позиционные аргументы,
- а z – именованный.
Следующие вызовы функции эквивалентны:
Основное ограничение состоит в том, именованные аргументы должны находиться после всех позиционных (если таковые имеются). Сами же именованные аргументы можно задавать в любом порядке, это освобождает программиста от необходимости помнить, в каком порядке были указаны аргументы функции в объявлении, важно лишь, как они называются.
Определение функции Python 3
Вы можете задать функции для реализации нужной вам функциональности. Вот простые правила для определения функции в Python.
- Ключевое слово для определения функции: def, за которым следуют имя функции и круглые скобки () с параметрами.
- Любые входные параметры или аргументы должны быть помещены в эти круглые скобки.
- В качестве первой команды может быть необязательная конструкция — строка документации функции (эта часть функции — пояснение зачем функция создана, очень рекомендуется использовать для облегчения понимания кода при работе в команде или при повторном возвращении к коду через длительный промежуток времени) .
- Блок кода в каждой функции начинается с двоеточия : и имеет отступ.
- Оператор return[выражение] возвращает результат из функции. Оператор return без аргументов аналогичен return None. Функции всегда возвращают значение, хотя бы None.
Синтаксис функции Python
По умолчанию, параметры parameter1, parameter2 имеют позиционное поведение, и вам необходимо сообщить их в том же порядке, в котором они были определены.
Пример реализации функции
Следующая функция принимает строку в качестве входного параметра и печатает ее на стандартном экране.
Вызов функции
В определении функции указывается имя функции, её параметры, а также тело функции (реализация требуемой функциональности).
Как только базовая структура функции создана, вы можете выполнить ее, вызвав ее из другой функции или непосредственно из Python prompt (командной оболочки) . Ниже приведен пример вызова функции printme():
Результат:
Аргументы функции
Вы можете вызвать функцию, используя следующие типы аргументов:
- Обязательные аргументы
- Ключевые аргументы
- Аргументы по умолчанию
- Аргументы переменной длины
Обязательные (позиционные) аргументы
Позиционные аргументы: указываются простым перечислением
Обязательные аргументы — это аргументы, переданные функции в правильном позиционном порядке. Здесь количество аргументов и их порядок в вызове функции должно точно соответствовать определению функции.
Чтобы вызвать функцию printme() , вам обязательно нужно передать один аргумент, иначе она выдаст следующую синтаксическую ошибку:
Ошибка (в функции Printme не указан аргумент):
Правильно указать аргумент так:
Ключевые аргументы
Ключевые аргументы: указываются перечислением ключ=значение
Когда вы используете ключевые аргументы в вызове функции, вызывающая сторона идентифицирует аргументы по имени параметра. Плюс в определении функции у ключевого параметра можно указать значение по-умолчанию.
Это позволяет пропускать аргументы или размещать их не по порядку, поскольку интерпретатор Python может использовать предоставленные ключевые слова (ключи) для сопоставления значений с параметрами. Создадим ключевые слова для функции printinfo() следующими способами:
Результат:
Важно! Позиционные и ключевые аргументы могут быть скомбинированы в одной функции. Позиционные параметры всегда идут перед ключевыми.
Преимущества ключевых аргументов в функциях
- Нет необходимости отслеживать порядок аргументов;
- У ключевых параметров есть значение по умолчанию, которое можно не передавать.
Аргументы по умолчанию
Аргумент по умолчанию — это аргумент, который принимает значение по умолчанию (задается в описании функции), если при вызове функции аргументу не передается значение.
Следующий пример дает представление об аргументах по умолчанию, он печатает возраст по умолчанию, если он не был передан:
Результат:
Аргументы переменной длины
Передача кортежа в функцию — Использование *args в Python
Вам может потребоваться разработать функцию для большего числа аргументов, чем Вы указали при определении функции. Эти аргументы называются аргументами переменной длины и не указываются в определении функции, в отличие от позиционных и ключевых аргументов.
В Python форма с одной звездочкой *args может использоваться в качестве параметра для отправки в список функций аргументов переменной длины без ключа. Стоит отметить, что звёздочка ( * ) является здесь важным элементом, так как слово args является общепринятой традиционной идиомой, хотя оно не поддерживается языком.
Синтаксис для функции с аргументами переменной длины следующий:
Звездочка (*) ставится перед именем переменной, которая содержит в себе кортеж значений без ключевых слов. Кортеж является необязательным параметром.
Рассмотрим простой пример:
Результат:
Еще один пример использования *args в функции Python:
Результат:
Поскольку мы использовали *args для отправки списка аргументов переменной длины в нашу функцию, мы смогли передать столько аргументов, сколько пожелали, в вызовы функции.
С помощью *args вы можете создать более гибкий код, который принимает различное количество аргументов без ключевых слов в вашей функции.
Передачи словаря переменной длины с аргументами в функцию **kwargs
**kwargs — сокращение от “keyword arguments”
Форма двойной звездочки **kwargs используется для передачи словарного словаря с аргументами переменной длины в функцию. Опять же, две звездочки ( ** ) являются здесь важным элементом, так как слово kwargs используется условно, но не поддерживается языком.
Мол *args , **kwargs может принять столько аргументов, которые вы хотели бы привести к этому. Однако **kwargs отличается от того, *args что вам нужно будет назначить ключевые слова.
Во-первых, давайте просто распечатаем **kwargs аргументы, которые мы передаем функции. Мы создадим короткую функцию для этого:
Давайте запустим программу выше и посмотрим на вывод:
В зависимости от версии Python 3, которую вы используете в данный момент, тип данных словаря может быть неупорядоченным. В Python 3.6 и выше вы получите пары ключ-значение по порядку, но в более ранних версиях пары будут выводиться в случайном порядке.
Важно отметить, что kwargs созданный словарь создан, и мы можем работать с ним так же, как мы можем работать с другими словарями.
Давайте создадим еще одну короткую программу, чтобы показать, как мы можем использовать **kwargs . Здесь мы создадим функцию для приветствия словаря имен. Сначала мы начнем со словаря из двух имен:
Использование **kwargs дает нам гибкость в использовании ключевых аргументов в нашей программе. Когда мы используем **kwargs в качестве параметра, нам не нужно знать, сколько аргументов мы в конечном итоге хотели бы передать функции.
Использование *args и **kwargs в вызовах функций
Мы также можем использовать *args и **kwargs для передачи аргументов в функции.
Сначала давайте рассмотрим пример с *args .
В функции выше, существует три параметра , определенный как arg_1 , arg_ и arg_3 . Функция распечатает каждый из этих аргументов. Затем мы создаем переменную, для которой задано итеративное значение (в данном случае кортеж ), и можем передать эту переменную в функцию с синтаксисом звездочки.
Когда мы запустим код, мы получим следующий вывод:
Мы также можем изменить вышеприведенную программу для типа данных итеративного списка с другим именем переменной. Давайте также объединим *args синтаксис с именованным параметром :
Если мы запустим программу выше, она выдаст следующий вывод:
Аналогично, **kwargs аргументы с ключевым словом могут использоваться для вызова функции. Мы установим переменную, равную словарю с 3 парами ключ-значение (мы будем использовать kwargs здесь, но она может называться как угодно), и передадим ее функции с 3 аргументами:
Мы можем использовать специальный синтаксис *args и **kwargs внутри определения функции, чтобы передать переменное число аргументов функции.
Создание функций, которые принимают *args и **kwargs лучше всего использовать в ситуациях, когда вы ожидаете, что количество входов в списке аргументов останется относительно небольшим. Использование *args и **kwargs в первую очередь для обеспечения удобочитаемости и удобства, но следует делать с осторожностью.
Комбинирование параметров *args и **kwargs в функции
При комбинировании параметров параметр с двумя звездочками записывается самым последним. Если в определении функции указывается комбинация параметров с одной звездочкой и двумя звездочками, то функция примет любые переданные ей параметры:
Результат:
Еще один пример использования комбинации *args & **kwargs:
Результат:
Порядок аргументов в функции Python
Аргументы внутри вызова функции должны стоять в определенном порядке:
- Позиционные аргументы (arg_1, arg_2)
- *args
- Ключевые аргументы (kw_1=»значение 1″, kw_2=»значение 2″)
- **kwargs
Рассмотрим детальный пример с использованием всех функций:
Результат:
Передача списка (list) по ссылке в функцию
Следующий результат подтверждает, что аргументы передаются по ссылке в функцию Python:
Пространства имен, области видимости и локальные функции
Область действия переменной — область видимости переменных
Переменные в программе могут быть доступны или недоступны в разных местах этой программы. Это зависит от того, где вы объявили переменную.
Область действия переменной определяет ту часть программы, в которой вы можете получить доступ к определенному идентификатору (т.е. к значению переменной и возможности эту переменную поменять). В Python есть две основные области видимости переменных:
- Глобальные переменные
- Локальные переменные
Область видимости переменной в Python называют также пространством имен. Любая переменная, которой присвоено значение внутри функции, по умолчанию попадает в локальное пространство имен.
Локальное пространство имен создается при вызове функции, и в него сразу же заносятся аргументы функции. По завершении функции локальное пространство имен уничтожается (хотя бывают и исключения, см. ниже раздел о замыканиях).
Переменные внутри функции – локальные. Поиск переменных: сперва среди локальных, потом среди глобальных.
Рассмотрим следующую функцию:
При вызове func() создается пустой список a, в него добавляется 5 элементов, а затем, когда функция завершается, список a уничтожается. Но допустим, что мы объявили a следующим образом:
Присваивать значение глобальной переменной внутри функции допустимо, но такие переменные должны быть объявлены глобальными с помощью ключевого слова global:
Функции можно объявлять в любом месте, в том числе допустимы локальные функции, которые динамически создаются внутри другой функции при ее вызове:
Здесь функция inner_function не существует, пока не вызвана функция outer_function. Как только outer_function завершает выполнение, inner_function уничтожается.
Не рекомендуется злоупотреблять ключевым словом global. Обычно глобальные переменные служат для хранения состояния системы. Если вы понимаете, что пользуетесь ими слишком часто, то стоит подумать о переходе к объектно-ориентированному программированию (использовать классы).
Вложенные функции могут обращаться к локальному пространству имен объемлющей функции, но не могут связывать в нем переменные. Подробнее смотрите в разделе о замыканиях.
Строго говоря, любая функция локальна в какой-то области видимости, хотя это может быть и область видимости на уровне модуля.
Возврат нескольких значений из одной функции
В Python существует возможность возвращать из функции несколько значений.
Вот простой пример:
В анализе данных и других научных приложениях это встречается сплошь и рядом, потому что многие функции вычисляют несколько результатов.
На самом деле, функция возвращает только один объект, кортеж, который затем распаковывается в результирующие переменные.
Этот пример можно было бы записать и так:
В таком случае return_value было бы кортежем, содержащим все три возвращенные переменные.
Иногда разумнее возвращать несколько значений не в виде кортежа, а в виде словаря:
Функции являются объектами
Поскольку функции в Python – объекты, становятся возможны многие конструкции, которые в других языках выразить трудно. Пусть, например, мы производим очистку данных и должны применить ряд преобразований к следующему списку строк:
Всякий, кому доводилось работать с присланными пользователями данными опроса, ожидает такого рода мусора. Чтобы сделать такой список строк пригодным для анализа, нужно произвести различные операции: удалить лишние пробелы и знаки препинания, оставить заглавные буквы только в нужных местах.
Первая попытка могла бы выглядеть так:
Другой подход, который иногда бывает полезен, – составить список операций, которые необходимо применить к набору строк:
Подобный функциональный подход позволяет задать способ модификации строк на очень высоком уровне. Степень повторной используемости функции clean_strings определенно возросла!
Функции можно передавать в качестве аргументов другим функциям, например встроенной функции map, которая применяет переданную функцию к коллекции:
Анонимные функции или Лямбда-функции. Lambda Function Python 3
- Лямбда-функции позволяют создавать «встроенные» функции, которые полезны для функционального программирования. Например, с Map, Filter или Reduce.
- Lambda — это инструмент для создания обработчиков обратного вызова (callback handlers).
Lambda Function — это анонимная однострочная функция, которая возвращает всегда 1 результат.
Определяются они с помощью ключевого слова lambda
ИмяФункции = lambda переменная_1, переменная_2, …, переменная_N : <выражение, которое использует переменные>
Например, функция equiv_anon :
эквивалентна функции short_function :
Лямбда-функции особенно удобны в ходе анализа данных, потому что, как вы увидите, во многих случаях функции преобразования данных принимают другие функции в качестве аргументов. Часто быстрее (и чище) передать лямбда-функцию, чем писать полноценное объявление функции или даже присваивать лямбда-функцию локальной переменной.
Рассмотрим такой простенький пример:
Можно было бы, конечно, написать [x * 2 for x in ints] , но в данном случае нам удалось передать функции apply_to_list пользовательский оператор.
Еще пример: пусть требуется отсортировать коллекцию строк по количеству различных букв в строке.
Для этого можно передать лямбда-функцию методу списка sort:
Для чего хороша лямбда-функция? Зачем нужная lambda function в Python?
Ответ:
- Нам не нужна лямбда функция, мы могли бы обойтись без нее. Но…
- Есть определенные ситуации, когда это удобно — lambda делает написание кода немного легче, а написанный код — немного чище.
Какие ситуации?
Что ж, ситуации, в которых нам нужна простая одноразовая функция: функция, которая будет использоваться только один раз.
Обычно функции создаются для одной из двух целей: (а) для уменьшения дублирования кода или (б) для модульности кода.
- Если ваше приложение содержит повторяющиеся фрагменты кода в разных местах, то вы можете поместить одну копию этого кода в функцию, дать имя функции, а затем — используя это имя функции — вызвать ее из разных мест в вашем коде.
- Если у вас есть кусок кода, который выполняет одну четко определенную операцию — но он действительно длинный и грубый и прерывает читаемый поток вашей программы, то вы можете извлечь этот длинный грубый код и поместить его в самостоятельную функцию.
Но предположим, что вам нужно создать функцию, которая будет использоваться только один раз — вызываться только из одного места в вашем приложении. Ну, во-первых, вам не нужно давать имя функции. Это может быть «анонимно». И вы можете просто определить его прямо там, где вы хотите его использовать. Вот где лямбда полезна.
Еще один пример использования lambda функции:
Неправильное использование: именование лямбда-выражений
PEP8, официальное руководство по стилю Python, советует никогда не писать такой код:
Вышеприведенный оператор создает анонимную функцию, а затем назначает ее переменной. Приведенный выше код игнорирует причину полезности лямбда-функций : лямбда-функции могут передаваться без необходимости вначале присваивать их переменной.
Если вы хотите создать однострочную функцию и сохранить ее в переменной, вы должны использовать def вместо этого:
PEP8 рекомендует это, потому что именованные функции — это обычная и понятная вещь. Именованная функция также имеет следующее преимущество: назначая нашей функции правильное имя, Вы упрощаете отладку кода. В отличие от функций, определенных с помощью def , лямбда-функции никогда не имеют имени (это всегда <lambda> ).
Если вы хотите создать функцию и сохранить ее в переменной, определите свою функцию с помощью def . Это именно то, для чего существует именованная функция. Не имеет значения, является ли ваша функция одной строкой кода или вы определяете функцию внутри другой функции, def отлично работает для этих случаев использования.
Неправильное использование: ненужные вызовы функций
Периодически встречаются лямбда-выражения, которые используются для подстановки в функции python, которые уже содержат функциональность для решения задачи. Нужно только посмотреть в документацию по функциям.
Например, возьмем этот код:
Программист , написавший этот код, вероятно, узнал, что лямбда-выражения используются для создания функции, которую можно передавать в другую функцию.
Поскольку abs (которая возвращает абсолютное значение числа) является функцией и все функции могут быть переданы, мы могли бы написать приведенный выше код следующим образом:
Теперь этот пример может показаться надуманным, но нередко чрезмерно используют лямбда-выражения таким образом. Вот еще один пример, который иногда встречается:
Поскольку мы принимаем те же аргументы, что и при передаче min , нам не нужен этот дополнительный вызов функции. Вместо этого мы можем просто передать min функцию key :
Вам не нужна лямбда-функция, если у вас уже есть другая функция, которая делает то, что вы хотите.
Замыкания: функции, возвращающие функции. Динамически сгенерированная функция
Замыканием называется любая динамически сгенерированная функция, возвращенная из другой функции. Основное свойство замыкания состоит в том, что оно имеет доступ к переменным, определенным в том локальном пространстве имен, в котором было создано.
Вот очень простой пример:
Разница между замыканием и обычной функцией Python состоит в том, что замыкание сохраняет доступ к пространству имен (функции), в котором было создано, даже если создавшая ее функция уже завершилась.
Так, в примере выше, возвращенное замыкание печатает строку «Я знаю секрет: 5», в какой бы момент ее ни вызвать. Хотя обычно создают замыкания со статическим внутренним состоянием (в данном случае только значение a), ничто не мешает включить в состав состояния изменяемый объект – словарь, множество, список – и затем модифицировать его.
Например, ниже приведена функция, которая возвращает функцию, запоминающую, с какими аргументами вызывалась объемлющая функция:
Однако следует иметь в виду одно техническое ограничение: изменять внутреннее состояние объектов (например, добавлять в словарь пары ключ-значение) можно, но связывать переменные в области видимости объемлющей функции – нельзя. Обойти это ограничение можно, например, путем модификации словаря или списка вместо присваивания значений переменным.
Возникает вопрос, зачем все это нужно? На практике можно написать очень общую функцию с кучей параметров, а затем изготовить на ее основе более простые специализированные функции.
Вот пример функции форматирования строк:
Каррирование: частичное фиксирование аргументов функции
В информатике термином каррирование обозначается процедура порождения новых функций из существующих путем фиксирования некоторых аргументов.
Пусть, например, имеется тривиальная функция сложения двух чисел:
Мы можем породить на ее основе новую функцию одной переменной, add_five, которая прибавляет к своему аргументу 5:
Говорят, что второй аргумент функции add_numbers каррирован. Ничего особо примечательного здесь нет, поскольку мы просто определили новую функцию, которая вызывает существующую.
Теперь запустим полный код:
Стандартный модуль functools упрощает эту процедуру за счет функции partial:
Также вернет 15
При обсуждении библиотеки pandas мы будем пользоваться этой техникой для создания специализированных функций преобразования временных рядов:
Python. Аргументы в функциях. Передача аргументов в функцию. Изменение аргументов в теле функции
В функцию могут передаваться аргументы. Аргументы – это изменяемые или неизменяемые объекты. В языке Python имеет значение, к какой категории объектов (изменяемых или неизменяемых) принадлежит аргумент.
Например, к изменяемым объектам относятся списки и словари. К неизменяемым объектам относятся числа, строки, кортежи.
Если в функцию передается неизменяемый объект, то этот объект передается «по значению». Это значит, что изменение этого объекта внутри функции не изменит его в вызывающем коде.
Если в функцию передается изменяемый объект, то этот объект передается по «указателю». Изменение такого объекта внутри функции повлияет на этот объект в вызывающем коде.
2. Примеры передачи неизменяемых объектов в функцию
2.1. Передача числа в функцию.
В примере, в демонстрационных целях реализована функция Mult2() , которая получает параметром число. В теле функции это число удваивается. Полученный результат выводится.
После запуска программа выдаст следующий результат
Как видно из результата, в функции значение числа num умножается на 2 и составляет 50. Однако, этот результат не передается в вызывающий код, здесь значение num остается равным 25 как до вызова функции. Это подтверждает передачу «по значению» неизменяемого объекта, которым есть число.
2.2. Передача строки в функцию
Демонстрируется работа функции ReverseStr() , которая реверсирует строку, получаемую параметром.
Результат выполнения программы
Так же, как и в предыдущих двух примерах, передача кортежа в функцию происходит по значению.
3. Примеры передачи изменяемых объектов в функцию
3.1. Передача списка в функцию
Демонстрируется функция, которая получает список в качестве параметра. Затем в теле функции этот список изменяется (изменяются первый и второй элементы списка).
Результат работы программы
Как видно из результата, изменение списка в теле функции приводит к изменению этого списка в вызывающем коде. Это означает, что список передается по принципу указателя языка C.
3.2. Передача словаря в функцию
Демонстрируется функция ChangeDict() которая получает словарь в качестве параметра. В теле функции изменяются отдельные элементы словаря, лежащие на позициях с номерами 0 и 2.
Результат работы программы
4. Способы избежания изменения объектов-аргументов в вызывающем коде
В случаях, когда нужно запретить изменение объекта списка внутри функции, можно использовать способы которые описаны ниже.
Способ 1. При передаче списка в функцию можно конвертировать этот список в кортеж с помощью операции tuple() . После этого изменить список в теле функции не удастся.
Нижеследующий код демонстрирует использование операции tuple() для конвертирования списка в кортеж.
Список LL передается в функцию PassList() как кортеж
После этого, изменить элемент списка LL в функции PassList() не удастся. Если запустить программу, то будет сгенерировано исключение с сообщением
Способ 2. При передаче списка в функцию можно использовать операцию среза [:] , как показано в следующей программе
В вышеприведенном коде при вызове функции с помощью строки
срез LL[:] осуществляет копию списка. Таким образом, изменения списка внутри функции не приведут к изменению списка в вызывающем коде, поскольку эти изменения будут выполняться над копией.
После запуска на выполнение, программа выдаст такой результат
5. Особенности передачи аргументов в функцию. Итоги
Для аргументов, которые передаются в функцию, можно выделить следующие особенности:
1. Если из внешнего кода вызывается функция с передачей ей аргумента, то в теле функции этот аргумент (объект) автоматически присваивается соответствующей локальной переменной функции.
Например. Демонстрируется автоматическое присвоение локальной переменной функции значения аргумента.
2. Аргументы функции – это ссылки на объекты. При передаче аргумента в функцию передается ссылка на объект. Передаваемые ссылки реализованы как указатели в языке C. Поскольку, при передаче в функцию аргумента, копируется ссылка на объект, то сам объект никогда не копируется. Иными словами, не создается автоматическая копия объекта при передаче его в функцию, осуществляется только копия ссылки.
3. Если в теле функции присвоить значение имени переданного параметра, то это не повлияет на значение внешнего аргумента в вызывающем коде. Это связано с тем, что имена аргументов в вызывающем коде становятся новыми именами в области видимости функции.
Например. В примере, в функции Func() изменяется значение параметра D на 25. В вызывающем коде был передан аргумент с таким самым именем D со значением 30. Однако, после вызова функции из вызывающего кода, значение внешнего аргумента D не изменилось, что и надо было доказать.
4. Если в функцию передается аргумент (объект), который есть изменяемым (список, словарь), то изменение этого аргумента внутри функции приведет к изменению аргумента в вызывающем коде. Это касается только изменения составных элементов объекта (отдельный элемент словаря или списка). Если попробовать изменить объект по его общему имени (с помощью операции присваивания = ), то изменений в вызывающем коде не будет (передается ссылка на объект, а именно ссылку изменить нельзя).
Например. В нижеследующем примере объявляются две функции, которые делают попытку изменить входной параметр-список по его имени: