Функции и методы в Python: передача функции в функцию. Декоратор
2026-03-10 21:54 Diff

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

Что надо знать о методах и функциях в Python?

Говоря о функциях в Python, нужно упомянуть два аспекта: 1) функция в Python — есть объект специального вида, который можно передавать в виде аргумента другим функциям; 2) внутри функций в Python вы можете создавать другие функции, а также вызывать их, возвращая результат посредством return.

Теперь давайте поговорим об этом подробнее.

Функция как объект в Python

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

>>> # исходный список >>> a = [1, 2, 3, 4, 5] >>> # функция, которая возводит в квадрат переданное ей число >>> sq = lambda x: x**2 >>> # проверка работы функции в Python >>> print(sq(5)) 25 >>> # получение списка квадратов >>> b = list(map(sq, a)) >>> print(b) [1, 4, 9, 16, 25]

В нашем примере мы передали функции map в виде первого аргумента функцию sq. Последняя будет по очереди применяться ко всем элементам нашего списка a.

Кроме того, в Python функция является специальным объектом, имеющим метод __call__(). Представьте, что мы создали следующий класс:

class DemoCall(): def __call__(self): return "Hello!"

Объект такого класса в Python мы сможем вызывать как функцию:

>>> hello = DemoCall() >>> hello() 'Hello!'

Функция внутри функции в Python

Функции в Python мы можем создавать, вызывать и возвращать из других функций. Кстати, на этом основана идея замыкания (closures) в Python.

Давайте создадим функцию, умножающую 2 числа:

def mul(a): def helper(b): return a * b return helper

В этой функции в Python реализованы два важных свойства: 1) внутри функции mul() мы создаём ещё одну функцию helper(); 2) функция mul() возвращает нам функцию helper() в качестве результата работы.

Вызов этой функции в Python:

Особенность заключается в том, что мы можем создавать на базе функции mul() собственные кастомизированные функции. Давайте создадим функцию в Python, умножающую на 3:

>>>three_mul = mul(3) >>>three_mul(5) 15

В результате была построена функция three_mul(), умножающая на 3 любое переданное ей число.

Декоратор функции в Python

Конструктивно речь идёт о некоторой функции, в качестве аргумента которого выступает другая функция. Декоратор в Python добавляет дополнительный функционал к функции, не меняя её содержимое.

Создание

Представьте, что мы имеем пару простых функций в Python:

def first_test(): print("Test function 1") def second_test(): print("Test function 2")

При этом мы желаем их дополнить таким образом, чтобы перед вызовом основного кода нашей функции печаталась строчка “Start function”, а в конце – строка “Stop function”.

Реализовать поставленную задачу можно несколькими методами. Во-первых, мы можем добавить необходимые строки в конец и начало каждой функции. Но вряд ли это удобно, ведь если мы пожелаем их убрать, придётся модифицировать тело функции.

Теперь поговорим о втором пути. Для начала создадим функцию:

def simple_decore(fn): def wrapper(): print("Start function") fn() print("Stop function") return wrapper

Теперь нужно обернуть функции в оболочку:

first_test_wrapped = simple_decore(first_test) second_test_wrapped = simple_decore(second_test)

Обратите внимание, что функции first_test и second_test не поменялись.

>>> first_test() Test function 1 >>> second_test() Test function 2

Наши функции second_test_wrapped и first_test_wrapped обладают функционалом, который нам и нужен.

>>> first_test_wrapped() Start function Test function 1 Stop function >>> first_test_wrapped() Start function Test function 1 Stop function

Теперь, если надо, чтобы так работали функции с именами first_test и second_test, делаем следующее:

first_test = first_test_wrapped second_test = second_test_wrapped

Проверяем:

>>> first_test() Start function Test function 1 Stop function >>> second_test() Start function Test function 2 Stop function

Выполненные нами действия и являются реализацией идеи декоратора.

Правда, вместо строк:

def first_test(): print("Test function 1") first_test_wrapped = simple_decore(first_test) first_test = first_test_wrapped

мы можем написать иначе:

@simple_decore def first_test(): print("Test function 1")

В нашем случае @simple_decore – это не что иное, как декоратор функции.

Передаём аргументы в функцию с помощью декоратора

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

def param_transfer(fn): def wrapper(arg): print("Start function: " + str(fn.__name__) + "(), with param: " + str(arg)) fn(arg) return wrapper

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

@param_transfer def print_sqrt(num): print(num**0.5)

Теперь давайте выполним данную функцию с аргументом 4:

>>> print_sqrt(4) Start function: print_sqrt(), with param: 4 2.0

Декораторы для методов класса в Python

С декоратором можно объявлять и методы классов. Давайте выполним модификацию декоратора param_transfer:

def method_decor(fn): def wrapper(self): print("Start method: " + str(fn.__name__)) fn(self) return wrapper

Теперь приступим к созданию класса для представления 2-мерного вектора (математического). В классе определим метод norm(), выводящий модуль вектора.

class Vector(): def __init__(self, px = 0, py = 0): self.px = px self.py = py @method_decor def norm(self): print((self.px**2 + self.py**2)**0.5)

Что же, осталось продемонстрировать работу нашего метода:

>>> vc = Vector(px=10, py=5) >>> vc.norm() Start method: norm 11.180339887498949

Возвращаем результат работы функции через декоратор

Зачастую создаваемые функции выполняют возвращение какого-либо значения. Чтобы это стало возможным осуществить через декоратор, нужно специальным образом построить нашу внутреннюю функцию:

def decor_with_return(fn): def wrapper(*args, **kwargs): print("Start method: " + str(fn.__name__)) return fn(*args, **kwargs) return wrapper

Возможно применение этого декоратора и для оборачивания функций, принимающих различные аргументы и возвращающие значение:

@decor_with_return def calc_sqrt(val): return val**0.5

Осталось выполнить функцию calc_sqrt() с параметром 16:

>>> tmp = calc_sqrt(16) Start method: calc_sqrt >>> print(tmp)