Главная страница

3. Элементы функционального программирования (lambda-функции, фу. Использование функций в языке Python


Скачать 0.56 Mb.
НазваниеИспользование функций в языке Python
Дата27.03.2023
Размер0.56 Mb.
Формат файлаpdf
Имя файла3. Элементы функционального программирования (lambda-функции, фу.pdf
ТипДокументы
#1018362

Тема: Использование функций в языке Python.
Элементы функционального программирования
На этом занятии вы познакомитесь с функциями высшего порядка и
декораторами, рассмотрите еще один способ определения функции с
помощью lambda-функции.
Функции высшего порядка
Функции как объект.
В языке Python все является объектом. Функция – не исключение.
Например, функция input() является объектом, который позволяет вводить какие-либо значения. Раз функция – это объект, значит с ней можно работать как с объектом, например, сохранить в переменную или вывести на экран
(см. пример 1).
Пример 1
read = input print
(read)
В примере 1 в переменную read сохраняется функция input() как объект. Обратите внимание, что для этого используется input без скобочек, иначе произойдет вызов функции. После присваивания выполняется команда print(), которая выводит объект read (или input). Результат работы программы можно увидеть на рис. 1.
Рис. 1. Результат работы программы из примера 1
В примере 1 read является псевдонимом функции input, т.е. возможно для ввода значения использовать не только input(), но и read() (см. пример
2).
Пример 2
read = input name_user = read() print
(
'Hello,'
, name_user +
'!'
)
Результат работы программы из примера 2 можно увидеть на рис. 2.

Рис. 2. Результат работы программы из примера 2
Функции высшего порядка
Любой объект можно передать как аргумент в функцию или вернуть из функции. Так как любая функция является объектом, то к ней применимы эти действия.
Функция высшего порядка – функция, которая принимает в качестве аргументов другие функции или возвращает другую функцию в качестве результата. Например, функция converter_number из примера 3 является функцией высшего порядка, т.к. при вызове своим аргументом принимает другую функцию.
Пример 3
def even
(number):
# сделать четное число
return number + number %
2 def odd
(number):
# сделать нечетное число
return number + (number %
2
==
0
) def converter_number
(function, number): return function(number) print
(converter_number(even,
12
)) print
(converter_number(even,
13
)) print
(converter_number(odd,
13
)) print
(converter_number(odd,
14
))
В примере 3 функции even и odd преобразовывают переданное число соответственно в четное и нечетное. Функция converter_number применяет к переданному числу number переданную функцию function и возвращает полученный результат (рис. 3).
Рис. 3. Результат работы программы из примера 3
Например, команда «print(converter_number(even, 13))» вернет результат применения функции even к числу 13 (получится 14).
Встроенная функция высшего порядка map
Функция map принимает два аргумента: функцию и контейнер
(итерируемый элемент, например, список), к каждому элементу которого применяется переданная функция. Результатом работы будет являться
итерируемый объект, который состоит из преобразованных элементов переданного контейнера (см. пример 4).
Пример 4
sp = [
'1'
,
'2'
,
'3'
,
'4'
,
'5'
] rez = map
(
int
, sp) print
(rez) print
(
list
(rez))
В примере 4 функция map вызывается с двумя аргументами: функцией
int и списком sp. В результате работы map создаст итерируемый объект, состоящий из элементов списка sp, преобразованных с помощью функции int
(рис. 4), т.е. из набора чисел от 1 до 5.
Рис. 4. Результат работы программы из примера 4
Обратите внимание, результат работы функции map – специальный итерируемый объект (). С помощью команды
list() его можно привести к списку (см. пример 4).
С помощью функции map можно, используя одну строку кода, ввести последовательность целых чисел и сохранить их в списке (см. пример 5).
Пример 5
sp = list
(
map
(
int
, input
().split())) print
(sp)
В примере 5 в переменную sp сохраняется итерируемый объект, приведенный к списку из целых чисел, которые были получены в результате применения функции int к результату работы команды input().split() (список строк, полученных разделением введенной строки по символам табуляции).
Результат работы программы из примера 5 можно увидеть на рис. 5.
Рис. 5. Результат работы программы из примера 5

Рассмотрим еще один пример. С помощью функции map и ранее написанных функций even и odd будем приводить все элементы данного списка целых чисел к четным или нечетным числам. Программу и результат ее работы можно увидеть в примере 6 и на рисунке 6 соответственно.
Пример 6
def even
(number):
# сделать четное число
return number + number %
2 def odd
(number):
# сделать нечетное число
return number + (number %
2
==
0
) sp = [
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
] print
(
list
(
map
(even, sp))) print
(
list
(
map
(odd, sp)))
Рис. 6. Результат работы программы из примера 6
Lambda-функции
Существует еще один способ определения функции – lambda-функции.
Это короткие функции без имени (их еще называют анонимными).
Базовый синтаксис lambda-функции: lambda «аргументы»: «выражение»
Она принимает указанный набор аргументов и возвращает значение указанного выражения (выражение только одно!). Обратите внимание, возращение значения происходит автоматически, без использования команды return.
В программе из примера 7 в первой строчке в переменную even сохраняется значение lambda-функции, которая принимает аргументом некоторое число x и возвращает значение выражения x + x % 2. Подобную функцию мы ранее уже создавали в примере 3 и 6 с помощью инструкции def. Результат работы программы можно увидеть на рис. 7.
Пример 7
even = lambda x: x + x %
2 print
(even(
4
)) print
(even(
5
))

Рис. 7. Результат работы программы из примера 7
Lambda-функцию можно совмещать с функцией map. Так, в примере 8 в переменную sp сохраняется список, состоящий из преобразованных с помощью lambda-функции элементов списка sp (см. пример 8). Результат работы программы можно увидеть на рис. 8.
Пример 8
sp = [
1
,
2
,
3
,
4
,
5
] rez = list
(
map
(
lambda x: x + x %
2
, sp)) print
(rez)
Рис. 8. Результат работы программы из примера 8
В примере 9 lambda-функция принимает на вход один аргумент и возвращает его размер с помощью команды len. Таким образом, с использованием функции map будет создан список из чисел – длин строк списка sp (см. рис. 9).
Пример 9
sp = [
'hello'
,
','
,
'world'
,
'!'
,
''
] rez = list
(
map
(
lambda x: len
(x), sp)) print
(rez)
Рис. 9. Результат работы программы из примера 9
Также lambda-функции часто используют в качестве ключа при сортировке списка. Например, можно отсортировать список строк по длине каждой строки (см. пример 10).
Пример 10
sp = [
'dog'
,
'stork'
,
'elephant'
,
'lynx'
] sp.sort(
key
=
lambda x: len
(x)) print
(sp)

Рис. 10. Результат работы программы из примера 10
В программе из примера 10 задан именованный параметр key – функция, по которой происходит сортировка. В нашем случае указана lambda-функция, которая возвращает длину строки.
Декораторы
Как было рассмотрено ранее, функцию можно записать в переменную и работать с ней как с переменной, в том числе и менять значение. Т.е. можно взять любую функцию как объект и изменить ее значение (см. пример 11).
Пример 11
def f
(s): k =
0 for i in s: k +=
1 return
'Количество элементов: '
+ str
(k) len = f print
(len(
'qwerty'
))
Рис. 11. Результат работы программы из примера 11
В примере 11 объекту len присваивается новое значение: функция f.
Теперь len является псевдонимом функции f и при вызове делает то же самое, что и f (см. рис. 12). Это же можно сделать без присваивания. Для этого можно написать функцию с именем len.
Подменять функции, особенно встроенные (input, print, len и т.д.) опасно, т.к. после присваивания нового значения старое уже не вернуть. Эту проблему можно избежать, если определить функцию локально. Тогда изменения не затронут глобальную функцию (подобно определению глобальной и локальной переменной).
В качестве примера можно переопределить функцию len внутри другой функции (см. пример 12).
Пример 12
def f
(s): return
'Количество элементов: '
+ str
(
len
(s))
def change_len
(): len = f print
(len(
'qwerty'
)) change_len() print
(
len
(
'qwerty'
))
Теперь функция len переопределяется локально в функции change_len, т.е. глобальная функция len не изменяется. Результат работы программы можно увидеть на рис. 12.
Рис. 12. Результат работы программы из примера 12
Из вывода видно, что при вызове функции change_len функция len работала как псевдоним функции f. Вне функции change_len функция len
работает как раньше (возвращает количество элементов переданного в качестве аргумента контейнера). Обратите внимание, в функции f использована старая, глобальная функция len. Теперь это можно сделать, т.к. глобально функция len не изменяется.
Рассмотрим код из примера 13. Пользователь должен ввести пароль, после чего выполняется функция print_info, которая изначально печатает строку «Пока!». Но эта функция переопределяется командой «
print_info =
change_f(print_info) с помощью другой функции change_f. Она (change_f) принимает как аргумент функцию и возвращает новую, которая работает на основе старой. Таким образом, мы изменили поведение функции
print_info.
Теперь она печатает разные сообщения (см. рис. 13) в зависимости от верного или неверного ввода пароля пользователем (результат хранится в глобальной переменной access).
Пример 13
def change_f
(function): global access def f
(): if access: print
(
'Здравствуй! Ты ввел правильный пароль!'
) function() else
: print
(
'Недостаточно прав доступа!'
) function() return f def print_info
():
print
(
'Пока!'
) print_info = change_f(print_info) access =
False print
(
'Введи пароль:'
) user_passw = input
() if user_passw ==
'1234567890'
: access =
True print_info()
Рис. 13. Результат работы программы из примера 13
Процесс, когда происходит переопределение функции таким образом, что новая функция использует старую, называется декорированием
функции. А функция, которая возвращает новую (в примере 13 это функция
change_f), называется
декоратором.
Команду
«
print_info
=
change_f(print_info)» можно заменить более удобным способом (см. пример
14).
Пример 14
def change_f
(function): global access def f
(): if access: print
(
'Здравствуй! Ты ввел правильный пароль!'
) function() else
: print
(
'Недостаточно прав доступа!'
) function() return f
@change_f def print_info
(): print
(
'Пока!'
) access =
False print
(
'Введи пароль:'
) user_passw = input
()
if user_passw ==
'1234567890'
: access =
True print_info()
Команда
«@change_f» говорит, что функция
print_info
будет задекорирована с помощью функции-декоратора change_f.
Вопросы к разделу:
1.
--- Что такое функция высшего порядка?
2.
--- Какие функции высшего порядка вы знаете?
3.
--- Что такое lambda-функция?
4.
--- Может ли lambda-функция иметь более одного аргумента?
5.
--- Может ли lambda-функция иметь более одного выражения?
6.
--- Как работает функция map?
7.
--- Бывают ли локальные и глобальные функции?
8.
--- Что значит переопределить функцию локально?
9.
--- Что такое декоратор? Как работает декорирование функции?
Дополнительные материалы к разделу:
1. --- https://tproger.ru/translations/demystifying-decorators-in-python/
2. --- https://proglib.io/p/vse-chto-nuzhno-znat-o-dekoratorah-python-2020-05-
09 3. --- https://pythonist.ru/map-filter-i-reduce-funkczii-v-python/


написать администратору сайта