Включите исполнение JavaScript в браузере, чтобы запустить приложение.
23 янв 2025

Что такое функции высшего порядка в Python

Функциями высшего порядка называются функции, которые принимают другие функции в качестве входных данных или возвращают их в качестве выходных данных. В статье подробно расскажем, что такое функции высшего порядка, как их определить и использовать в Python.

Зачем нужны функции высшего порядка

В Python функция высшего порядка — это функция, которая удовлетворяет одному или нескольким из следующих критериев:

  • позволяет передавать другие функции в качестве параметров;
  • может отправлять обратно другие функции;
  • создает новые функции в своем теле.

Такие функции считаются мощным инструментом абстрагирования и повторного использования кода. Они позволяют писать более лаконичный и выразительный код, избегать повторов и ошибок. 

Встроенные функции высшего порядка

Map. Нужна для преобразования массива путем применения функции к каждому его элементу. В качестве аргумента map() принимает функцию, которая используется для изменения каждого элемента. Конечный массив содержит преобразованные элементы.

Пример:

def mul(i):

    return i * i

num = (3, 5, 7, 11, 13)

resu = map(mul, num)

print(resu)

# making the map object readable

mul_output = list(resu)

print(mul_output)

[9, 25, 49, 121, 169]
py

Min. Выполняет поиск минимального значения в списке. Принимает один обязательный параметр и три необязательных. При желании можно добавить дополнительные объекты в качестве постоянных аргументов, выполнить сортировку с помощью ключа.

Пример:

arr = [1, 2, 3, 4, 5]

min(arr)

=> 1

min(0, -2, 1, 8, 5)

=> -2

students = [

    {'name': 'Jimmy', 'age': 15},

    {'name': 'Hector', 'age': 18},

    {'name': 'Paige', 'age': 16}

]

min(students, key=lambda x: x['age'])

=> {'name': 'Jimmy', 'age': 15}

min([], default=0)

=> 0
py

Max. Находит максимальное значение в повторяющейся переменной.

Пример:

arr = [1, 2, 3, 4, 5]

max(arr)

=> 5

max(0, -2, 1, 8, 5)

=> 8

students = [

    {'name': 'Jimmy', 'age': 15},

    {'name': 'Hector', 'age': 18},

    {'name': 'Paige', 'age': 16}

]

max(students, key=lambda x: x['age'])

=> {'name': 'Hector', 'age': 18}

max([], default=100)

=> 100
py

Sort. Метод возвращает новую отсортированную версию списка. Принимает один обязательный и два необязательных аргумента (reverse и key). Обязательный аргумент — список. Необязательный параметр reverse переворачивает отсортированный список, а необязательный параметр key —  функция, на основе которой выполняется сортировка. 

Пример:

# List of Integers

numbers = [1, 3, 4, 2]

# Sorting list of Integers

numbers.sort()

print(numbers)

# List of Floating point numbers

decimalnumber = [2.01, 2.00, 3.67, 3.28, 1.68]

# Sorting list of Floating point numbers

decimalnumber.sort()

print(decimalnumber)

# List of strings

words = ["Geeks", "For", "Geeks"]

# Sorting list of strings

words.sort()

print(words)

Output:

[1, 2, 3, 4]

[1.68, 2.0, 2.01, 3.28, 3.67]

['For', 'Geeks', 'Geeks']
py

Filter.Применяется для фильтрации элементов из массива на основе условия. filter() принимает в качестве аргумента функцию, которая используется для проверки каждого элемента. Итоговый массив содержит только те элементы, которые прошли проверку.

Пример:

nums = [5, 10, 23, 64, 42, 53, 93, 2, 0, -14, 6, -22, -13]

#Filter all the odd numbers from the list

odd = filter(lambda p : p%2 != 0, nums)

#Filter all the even numbers from the list

even = filter(lambda p: p%2 == 0, nums)

print("The list of odd numbers is: ", list(odd))

print("The list of even numbers is: ", list(even))
py

Здесь используются lambda-функции. Они не считаются функциями высшего порядка, но могут выступать в качестве аргументов.

Пример — создание списка словарей, в которых хранятся сведения о книгах. Там будут имена авторов, название, цена. Цель — отфильтровать информацию о тех книгах, стоимость которых превышает фиксированную цену.

books = [

   {"Title":"Angels and Demons", "Author":"Dan Brown", "Price":500},

   {"Title":"Gone Girl", "Author":"Gillian Flynn", "Price":730},

   {"Title":"The Silent Patient", "Author":"Alex Michaelidis", "Price":945},

   {"Title":"Before I Go To Sleep", "Author":"S.J Watson", "Price":400}

   ]

def func(book):

   if book["Price"] > 500:

       return True

   else:

       return False

filtered_object = filter(func, books)

for d in filtered_object:

   print(dict(d)["Title"])    

Output:

Gone Girl 
The Silent Patient
py

Модуль Functools

reduce(). Функция и итерируемая переменная передаются в reduce. Она применяет предоставленную функцию ко всем элементам итерируемой переменной кумулятивно слева направо, прежде чем вернуть одно значение.

Сначала аргумент применяется к первым двум элементам. Значение, возвращаемое этим первоначальным вызовом, становится первым аргументом, третий элемент — вторым аргументом. 

reduce() можно использовать для нахождения суммы списка чисел:

from functools import reduce  
  
# Function that returns the sum of two numbers  
def add(a, b):  
    return a + b  
  
# Our Iterable  
num_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]  
  
# add function is passed as the first argument, and num_list is passed as the second argument  
sum = reduce(add, num_list)  
print(f"Sum of the integers of num_list : {sum}")  
  
# Passing 10 as an initial value  
sum = reduce(add, num_list, 10)  
print(f"Sum of the integers of num_list with initial value 10 : {sum}")  

Output:

Sum of the integers of num_list : 55
Sum of the integers of num_list with initial value 10 : 65
py

Здесь reduce() нужна для применения add, которая возвращает сумму двух значений к каждой паре элементов в списке чисел. В результате получается сумма всех элементов.

partial(). Если функция принимает два параметра «a» и «b», из нее может быть построена частичная функция с «a» в качестве предварительно заполненного аргумента, и затем она может быть вызвана с «b» в качестве единственного параметра. Метод partial() в Functools используется для создания частичных объектов. Благодаря этому можно сделать репликацию существующих функций с некоторыми уже установленными параметрами.

Пример:

from functools import partial

# Function to scale a value

def scale_data(value, factor):

    return value * factor

# Create partial functions for specific scaling factors

scale_by_2 = partial(scale_data, factor=2)

scale_by_10 = partial(scale_data, factor=10)

data = [1, 2, 3, 4, 5]

scaled_by_2 = list(map(scale_by_2, data))   # Scales by 2

scaled_by_10 = list(map(scale_by_10, data))  # Scales by 10

print(scaled_by_2)  

print(scaled_by_10) 

Output:

[2, 4, 6, 8, 10]

[10, 20, 30, 40, 50]
py

singledispatch(). Преобразует функцию в универсальный формат. Готовый вариант может вести себя по-разному в зависимости от типа первого аргумента. Чтобы добавить перегруженные реализации, используется атрибут register().

Пример создания метода, который может обрабатывать несколько типов:

from functools import singledispatch

from decimal import Decimal

@singledispatch

def fun(s):

    print(s)

@fun.register(float)

@fun.register(Decimal)

def _3(s):

    print(round(s, 2))

fun(2.34)

fun(Decimal(4.897))

Output :

2.34

4.90
py

cached_property(). Преобразует метод класса в свойство, значение которого вычисляется только один раз, а затем кэшируется как обычный атрибут. Кэшированный результат будет доступен до тех пор, пока объект или экземпляр класса не удален.

Пример:

from functools import cached_property, reduce

class ListProduct:

    lst = []

    def __init__(self):

        self.lst = [1, 2, 3, 4, 6, 9]

    def product(self):

        print("product() method called.")

        return reduce(lambda x, y: x * y, self.lst)

    @cached_property

    def product_of_elements(self):

        print("product_of_elements() method called.")

        return reduce(lambda x, y: x * y, self.lst)

ListProductObject = ListProduct()

product = ListProductObject.product()

print("Product without caching - ", product)

print("--"*5)

product = ListProductObject.product()

print("Product without caching - ", product)

print("--"*5)

product = ListProductObject.product_of_elements

print("Product with caching - ", product)

print("--"*5)

product = ListProductObject.product_of_elements

print("Product with caching - ", product)
py

total_ordering(). Методы упорядочения сравнения класса используются для сравнения объектов класса. Для любого класса есть шесть методов упорядочения сравнения:

  • __ lt__(): меньше, чем метод;
  • __le__(): меньше или равно методу;
  • __ gt__(): больше, чем метод;
  • __ge__(): больше или равно методу;
  • __eq__(): равно методу.

Например, нужно сравнить объекты класса. Для этого предоставляют реализации всех методов упорядочения сравнения в классе. 

Можно упростить процесс с помощью total_ordering. Необходимо определить любой из методов упорядочения сравнения, а функция предоставит остальные методы. Класс также должен добавить метод __eq__().

Например:

from functools import total_ordering

@total_ordering

class Person:

    def __init__(self, age):

        self.age = age

    def __lt__(self, other):

        return self.age < other.age

    def __eq__(self, other):

        return self.age == other.age

person1 = Person(10)

person2 = Person(20)

print("Person(10) > Person(20) ? ", person1 > person2)

print("Person(10) == Person(20) ? ", person1 == person2)

print("Person(10) >= Person(20) ? ", person1 >= person2)

print("Person(10) < Person(20) ? ", person1 < person2)

print("Person(10) <= Person(20) ? ", person1 <= person2)
py

wraps(). Это декоратор, который применяется к первичной функции. Копирует атрибуты __name__ и __doc__.

   from functools import wraps

    def my_decorator(f):

        @wraps(f)

        def wrapper(*args, **kwargs):

            """A wrapper function"""

            # Do something before

            result = f(*args, **kwargs)

            # Do something after

            return result

        return wrapper

    @my_decorator

    def greet():

        """Returns a friendly greeting"""

        return 'Hello!'

    print(greet.__name__)  # Outputs: greet

    print(greet.__doc__)   # Outputs: Returns a friendly greeting
py

В чем польза функций высшего порядка

У функций высшего порядка есть ряд преимуществ перед традиционными функциями в программировании. Они позволяют писать более абстрактный, гибкий и многократно используемый код, упрощают тестирование и отладку кода, помогают разбивать сложные задачи на более мелкие и понятные.

Еще одно преимущество — положительное влияние на развитие функционального программирования. Это парадигма, которая делает упор на неизменяемость, чистые функции и возможность компоновки. Использование этих методов помогает писать более модульный код, который прост в использовании и не подвержен ошибкам.

Благодаря им получается делать код более коротким, устранять повторяющиеся или избыточные элементы. Так код будет более понятным и удобным в обслуживании, что сказывается на командной работе — например, когда несколько разработчиков участвуют в одном проекте.

Заключение

Функции высшего порядка предлагают лаконичный способ манипулирования данными, помогают выполнять сложные операций более простым способом. Включение этих функций в код на Python может привести к созданию эффективных и понятных решений. Их можно применять для оптимизации кода, повышения удобочитаемости. Освоение таких методов поможет погрузиться в разработку на Python.