Функции высшего порядка — это важная концепция в Python. В Python все является объектом, включая функции. Это означает, что функции можно передавать в качестве аргументов другим функциям как и любой другой объект.
Функции, которые можно передавать в качестве аргументов или возвращать из других функций, известны как объекты первого класса или граждане первого класса.
В этом уроке мы научимся работать с объектами первого класса, функциями высшего порядка и лямбда-функциями.
Объекты первого класса
В Python функции являются объектами первого класса. Это означает, что их можно передавать в качестве аргументов другим функциям, возвращать как значения из других функций и хранить в переменных или структурах данных как любой другой объект. Это позволяет использовать функции как строительные блоки для более сложных программ.
Напишем пример, чтобы посмотреть, как функции используются в качестве объекта первого класса:
def hello(name):
print(f"Hello, {name}!")
greeting_function = hello
greeting_function("Hexlet")
# "Hello, Hexlet!"
В этом примере мы определяем функцию hello
, которая принимает один аргумент и печатает приветствие. Затем мы присваиваем функцию переменной greeting_function
и вызываем ее с аргументом.
Рассмотрим другой пример с передачей функции в качестве аргумента другой функции:
def apply_function(numbers, function):
results = []
for number in numbers:
result = function(number)
results.append(result)
return results
def square(number):
return number ** 2
numbers = [1, 2, 3, 4, 5]
squared_numbers = apply_function(numbers, square)
print(squared_numbers)
# [1, 4, 9, 16, 25]
В этом примере функция apply_function
принимает в качестве аргументов список чисел и функцию. Функция apply_function
применяет переданную функцию к каждому числу в списке и возвращает новый измененный список. Функция square
возводит число в квадрат, и используется в качестве аргумента функции apply_function
.
Объекты первого класса также позволяют возвращать функции из другой функции:
def make_multiplier(n):
def multiplier(x):
return x * n
return multiplier
times_2 = make_multiplier(2)
times_3 = make_multiplier(3)
print(times_2(5)) # 10
print(times_3(5)) # 15
В этом примере функция make_multiplier
принимает число n
и возвращает новую функцию, которая умножает свой аргумент на n
. Затем эта функция применяется, чтобы создать две новые функции times_2
и times_3
, которые умножают свой аргумент на 2 и 3 соответственно. В итоге вызывается функция с аргументом 5, чтобы увидеть их результаты.
Функции высшего порядка
Функции, которые принимают другие функции в качестве аргументов и/или возвращают функции в качестве результатов, называются функциями высшего порядка или ФВП. Их можно использовать для инкапсуляции многократно используемого поведения и создания более абстрактного кода, о котором легче рассуждать.
Например, встроенные функции map
и filter
в Python являются функциями высшего порядка, которые работают с итерируемыми объектами и применяют функцию к каждому элементу итерируемого объекта.
Рассмотрим следующий пример функции высшего порядка:
def repeat(func, n):
for i in range(n):
func()
def hello():
print("Hello, world!")
repeat(hello, 3)
Вывод будет следующим:
Hello, world!
Hello, world!
Hello, world!
Этот код использует функцию repeat()
для многократного вызова функции hello()
.
Рассмотрим другой пример с возвратом функции:
def double(function):
def inner(argument):
return function(function(argument))
return inner
def multiply_by_five(x):
return x * 5
double(multiply_by_five)(3)
# 75
В этом примере в теле функции double
создается функция inner
и возвращается в роли результата. Так как вызов double
возвращает функцию, мы можем сразу сделать второй вызов ((3)
). Он уже даст результат двойного применения исходной функции к аргументу.
Имя inner
довольно часто используется, чтобы называть функции, которые создаются на лету внутри внешней функции.
Но мы могли бы и не вызвать функцию-значение сразу, а вместо этого сохранить в переменную:
multiply_by_25 = double(multiply_by_five)
multiply_by_25
# <function double.<locals>.inner at 0x7fd1975c58c8>
multiply_by_25(1)
# 25
multiply_by_625 = double(multiply_by_25)
multiply_by_625
# <function double.<locals>.inner at 0x7fd1968f41e0>
multiply_by_625(1)
# 625
При выводе значения ссылки multiply_by_25
отображается double.<locals>.inner
— та самая созданная на лету функция inner
. И в случае multiply_by_625
функция называется inner
, но адрес в памяти другой — большое шестнадцатеричное число после "at".
Одним из полезных применений функций высшего порядка является использование их для определения анонимных функций — лямбда-функций.
Лямбда-функции
В Python лямбда функция — это небольшая анонимная функция, которая может быть определена без имени. Лямбда-функции часто используются там, где требуется небольшая, одноразовая функция. Синтаксис для определения лямбда-функции в Python следующий:
lambda arguments: expression
Здесь arguments
— это список входных аргументов функции, который разделен запятыми. А expression
— это тело функции, значение которой возвращает лямбда-функция.
Например, лямбда-функция, которая принимает два аргумента и возвращает их сумму, может быть определена следующим образом:
sum = lambda x, y: x + y
Это создает лямбда-функцию, которая принимает два аргумента x
и y
и возвращает их сумму. Затем лямбда-функцию можно вызывать как любую другую функцию:
result = sum(2, 3)
print(result)
# 5
Лямбда-функции также можно использовать в сочетании с другими функциями, такими как map
, filter
и reduce
. С их помощью можно создать краткий и выразительный код. Например, следующий код использует лямбда-функцию с функцией map
для возведения в квадрат каждого элемента списка:
numbers = [1, 2, 3, 4, 5]
squares = map(lambda x: x**2, numbers)
print(list(squares))
# [1, 4, 9, 16, 25]
В этом коде лямбда-функция lambda x: x**2
передается в качестве первого аргумента функции map
. Это создает новый объект-итератор, который применяет лямбда-функцию к каждому элементу списка numbers
. В результате получается новый список квадратных чисел.
Лямбда-функции — мощный инструмент в Python для создания небольших анонимных функций, которые можно использовать в самых разных контекстах. Однако их следует использовать с осторожностью, поскольку их лаконичный синтаксис иногда может затруднить чтение и понимание кода.
Выводы
В этом уроке мы научились работать с объектами первого класса, функциями высшего порядка и лямбда-функциями. Функции высшего порядка — это очень мощный инструмент в умелых руках. В следующем уроке мы рассмотрим несколько таких функций, которые полезны с практической точки зрения.
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
- Статья «Как учиться и справляться с негативными мыслями»
- Статья «Ловушки обучения»
- Статья «Сложные простые задачи по программированию»
- Вебинар «Как самостоятельно учиться»
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.