HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-26
1 <p>В программировании часто возникают задачи, когда нужно добавить поведение к уже существующим функциям или классам. Например, логирование, проверку входных данных или замер времени выполнения функции. В таких случаях использование декораторов может значительно упростить решение задачи.</p>
1 <p>В программировании часто возникают задачи, когда нужно добавить поведение к уже существующим функциям или классам. Например, логирование, проверку входных данных или замер времени выполнения функции. В таких случаях использование декораторов может значительно упростить решение задачи.</p>
2 <p>В этом уроке мы рассмотрим, что такое декораторы и как их использовать, чтобы добавлять дополнительную функциональность к существующим функциям.</p>
2 <p>В этом уроке мы рассмотрим, что такое декораторы и как их использовать, чтобы добавлять дополнительную функциональность к существующим функциям.</p>
3 <h2>Что такое декораторы</h2>
3 <h2>Что такое декораторы</h2>
4 <p>Ранее мы рассматривали как можно "запомнить" передаваемые в функцию значения с помощью замыканий. Напомним как выглядит синтаксис:</p>
4 <p>Ранее мы рассматривали как можно "запомнить" передаваемые в функцию значения с помощью замыканий. Напомним как выглядит синтаксис:</p>
5 <p>В этом примере мы создаем функцию outer(), которая принимает аргумент arg1 и возвращает внутреннюю функцию inner(). Внутренняя функция принимает аргумент arg2 и возвращает сумму arg1 и agr2.</p>
5 <p>В этом примере мы создаем функцию outer(), которая принимает аргумент arg1 и возвращает внутреннюю функцию inner(). Внутренняя функция принимает аргумент arg2 и возвращает сумму arg1 и agr2.</p>
6 <p>Может запутать одновременное определение функции и возврат ее же. Но если мы вспомним, что определение функции это присваивание функции имени переменной, а также, что функции это данные, то пример можно представить как:</p>
6 <p>Может запутать одновременное определение функции и возврат ее же. Но если мы вспомним, что определение функции это присваивание функции имени переменной, а также, что функции это данные, то пример можно представить как:</p>
7 <p>Мы заменили именованную функцию лямбдой, и теперь присваивание ничем не отличается, как если бы мы присвоили переменной inner число или строку.</p>
7 <p>Мы заменили именованную функцию лямбдой, и теперь присваивание ничем не отличается, как если бы мы присвоили переменной inner число или строку.</p>
8 <p>Но если функции всего лишь данные, то можно ли их также "запоминать" в замыканиях?</p>
8 <p>Но если функции всего лишь данные, то можно ли их также "запоминать" в замыканиях?</p>
9 <p>Остановимся и разберем пример выше. В нем мы создаем замыкание, но теперь, вместо числа в замыкание передается функция. Внешняя функция запомнила переданную в нее функцию. Осталось лишь передать аргументы и вызвать замкнутую функцию с ними. В дополнение, мы смогли распечатать переданную функцию и ее аргументы, при этом код самой функции square() мы не меняли.</p>
9 <p>Остановимся и разберем пример выше. В нем мы создаем замыкание, но теперь, вместо числа в замыкание передается функция. Внешняя функция запомнила переданную в нее функцию. Осталось лишь передать аргументы и вызвать замкнутую функцию с ними. В дополнение, мы смогли распечатать переданную функцию и ее аргументы, при этом код самой функции square() мы не меняли.</p>
10 <p>Функции выше называются декораторами.<strong>Декораторы</strong>в Python - это функции, которые принимают другую функцию в качестве аргумента, добавляют к ней дополнительную функциональность и возвращают функцию с измененным поведением. Декораторы позволяют изменять поведение функций и классов с помощью добавления или изменения их функциональности без изменения самого кода.</p>
10 <p>Функции выше называются декораторами.<strong>Декораторы</strong>в Python - это функции, которые принимают другую функцию в качестве аргумента, добавляют к ней дополнительную функциональность и возвращают функцию с измененным поведением. Декораторы позволяют изменять поведение функций и классов с помощью добавления или изменения их функциональности без изменения самого кода.</p>
11 <p>Также, как вы могли заметить, декораторы это частный случай функции высшего порядка (принимаем функцию) и использования замыкания вместе.</p>
11 <p>Также, как вы могли заметить, декораторы это частный случай функции высшего порядка (принимаем функцию) и использования замыкания вместе.</p>
12 <h2>Использование декораторов</h2>
12 <h2>Использование декораторов</h2>
13 <p>Декораторы используются в Python повсеместно: для логирования, кеширования, добавления нового функционала, используются в тестовых и веб-фреймворках.</p>
13 <p>Декораторы используются в Python повсеместно: для логирования, кеширования, добавления нового функционала, используются в тестовых и веб-фреймворках.</p>
14 <p>Предположим, что у нас есть функция, которая суммирует числа:</p>
14 <p>Предположим, что у нас есть функция, которая суммирует числа:</p>
15 <p>Создадим декоратор, который добавит к этой функции функциональность для отладки:</p>
15 <p>Создадим декоратор, который добавит к этой функции функциональность для отладки:</p>
16 <p>Этот декоратор принимает функцию в качестве аргумента и возвращает новую функцию-обертку, которая добавляет отладочные сообщения в процесс выполнения исходной функции. Заметьте, что внутренняя функция принимает сразу все аргументы с помощью *args и **kwargs. Так мы можем создавать "всеядные" обертки.</p>
16 <p>Этот декоратор принимает функцию в качестве аргумента и возвращает новую функцию-обертку, которая добавляет отладочные сообщения в процесс выполнения исходной функции. Заметьте, что внутренняя функция принимает сразу все аргументы с помощью *args и **kwargs. Так мы можем создавать "всеядные" обертки.</p>
17 <p>Применим этот декоратор к функции sum():</p>
17 <p>Применим этот декоратор к функции sum():</p>
18 <p>Проблема в коде выше, что теперь функция называется debugged_sum(), и нужно будет изменить весь код, что использовал sum(). Но ведь имя функции это всего лишь имя переменной, и мы можем перезаписать новую, декорированную функцию в ту же переменную.</p>
18 <p>Проблема в коде выше, что теперь функция называется debugged_sum(), и нужно будет изменить весь код, что использовал sum(). Но ведь имя функции это всего лишь имя переменной, и мы можем перезаписать новую, декорированную функцию в ту же переменную.</p>
19 <p>Теперь функция sum() будет выполняться с дополнительными отладочными сообщениями. А также весь код, использующий функцию sum() будет использовать новую функцию.</p>
19 <p>Теперь функция sum() будет выполняться с дополнительными отладочными сообщениями. А также весь код, использующий функцию sum() будет использовать новую функцию.</p>
20 <p>Чтобы не добавлять запись вида func = decorator(func) каждый раз, в Python добавили синтаксический сахар - @decorator</p>
20 <p>Чтобы не добавлять запись вида func = decorator(func) каждый раз, в Python добавили синтаксический сахар - @decorator</p>
21 <p>Также мы можем создавать несколько декораторов для одной функции, которые будут применяться последовательно:</p>
21 <p>Также мы можем создавать несколько декораторов для одной функции, которые будут применяться последовательно:</p>
22 <p>В этом примере сначала применится декоратор времени выполнения, а затем отладочный декоратор.</p>
22 <p>В этом примере сначала применится декоратор времени выполнения, а затем отладочный декоратор.</p>
23 <h2>Состояние</h2>
23 <h2>Состояние</h2>
24 <p>Отличительная черта функций, что они не хранят состояния. Функции, мы говорим о чистых функциях, лишь преобразуют входные данные в выходные. Или как еще говорят, "отображают" входное множество на выходное.</p>
24 <p>Отличительная черта функций, что они не хранят состояния. Функции, мы говорим о чистых функциях, лишь преобразуют входные данные в выходные. Или как еще говорят, "отображают" входное множество на выходное.</p>
25 <p>Но замыкания позволяют запоминать значения и использовать их в последующих вычислениях.</p>
25 <p>Но замыкания позволяют запоминать значения и использовать их в последующих вычислениях.</p>
26 <p>Замыкания, как и декораторы, позволяют нам создавать на базе функций собственные объекты и систему управления ими.</p>
26 <p>Замыкания, как и декораторы, позволяют нам создавать на базе функций собственные объекты и систему управления ими.</p>
27 <h2>Декораторы с параметрами</h2>
27 <h2>Декораторы с параметрами</h2>
28 <p>Что если мы хотели бы вызывать обернутую функцию с разными настройками? Для этого нам понадобятся декораторы с параметрами.</p>
28 <p>Что если мы хотели бы вызывать обернутую функцию с разными настройками? Для этого нам понадобятся декораторы с параметрами.</p>
29 <p>Общий синтаксис декоратора с параметрами выглядит так:</p>
29 <p>Общий синтаксис декоратора с параметрами выглядит так:</p>
30 <p>К обычному декоратору мы добавляем еще один слой с параметрами. И, конечно, в качестве параметров мы можем передавать другие функции:</p>
30 <p>К обычному декоратору мы добавляем еще один слой с параметрами. И, конечно, в качестве параметров мы можем передавать другие функции:</p>
31 <p>И даже функции с собственными параметрами, используя замыкания:</p>
31 <p>И даже функции с собственными параметрами, используя замыкания:</p>
32 <p>Декоратор filter_by() принимает функцию фильтрации less_than(), затем применяет ее к аргументам обернутой функции, и вызывает обернутую функцию с новыми аргументами.</p>
32 <p>Декоратор filter_by() принимает функцию фильтрации less_than(), затем применяет ее к аргументам обернутой функции, и вызывает обернутую функцию с новыми аргументами.</p>
33 <h2>Выводы</h2>
33 <h2>Выводы</h2>
34 <p>Мы изучили декораторы, мощный механизм для расширения функций. Существует большое количество готовых декораторов, доступных в стандартной библиотеке Python и других библиотеках. Некоторые из них позволяют кэшировать результаты функций, обеспечивать авторизацию и безопасность, профилировать код, проверять типы данных и многое другое.</p>
34 <p>Мы изучили декораторы, мощный механизм для расширения функций. Существует большое количество готовых декораторов, доступных в стандартной библиотеке Python и других библиотеках. Некоторые из них позволяют кэшировать результаты функций, обеспечивать авторизацию и безопасность, профилировать код, проверять типы данных и многое другое.</p>
35 <p>Декораторы могут повлиять на производительность кода, поэтому их следует использовать с умом и осторожностью. Также нужно учитывать, что декораторы могут усложнить отладку кода и сделать его менее понятным для других разработчиков.</p>
35 <p>Декораторы могут повлиять на производительность кода, поэтому их следует использовать с умом и осторожностью. Также нужно учитывать, что декораторы могут усложнить отладку кода и сделать его менее понятным для других разработчиков.</p>
36 <p>При этом декораторы являются сильным инструментом, который позволяет легко добавлять дополнительную функциональность к существующим функциям и классам и не изменять их исходный код.</p>
36 <p>При этом декораторы являются сильным инструментом, который позволяет легко добавлять дополнительную функциональность к существующим функциям и классам и не изменять их исходный код.</p>