1 added
1 removed
Original
2026-01-01
Modified
2026-02-21
1
<p><a>#статьи</a></p>
1
<p><a>#статьи</a></p>
2
<ul><li>1 дек 2020</li>
2
<ul><li>1 дек 2020</li>
3
<li>0</li>
3
<li>0</li>
4
</ul><p>На собеседованиях только и разговоров, что о декораторах. Разбираемся на пальцах, что это.</p>
4
</ul><p>На собеседованиях только и разговоров, что о декораторах. Разбираемся на пальцах, что это.</p>
5
<p> vlada_maestro / shutterstock</p>
5
<p> vlada_maestro / shutterstock</p>
6
<p>Кандидат философских наук, специалист по математическому моделированию. Пишет про Data Science, AI и программирование на Python.</p>
6
<p>Кандидат философских наук, специалист по математическому моделированию. Пишет про Data Science, AI и программирование на Python.</p>
7
<p>Итак, вы на собеседовании на вакансию джуна-пайтониста. Всё идёт хорошо: вы объяснили про кортежи и списки, про принципы ООП и структуры данных, даже решили небольшую задачку, и вдруг:</p>
7
<p>Итак, вы на собеседовании на вакансию джуна-пайтониста. Всё идёт хорошо: вы объяснили про кортежи и списки, про принципы ООП и структуры данных, даже решили небольшую задачку, и вдруг:</p>
8
<p>- Расскажите, пожалуйста, про декораторы в Python.</p>
8
<p>- Расскажите, пожалуйста, про декораторы в Python.</p>
9
<p>В большинстве случаев будет достаточно сказать своими словами, что такое декоратор, и написать простейший код.</p>
9
<p>В большинстве случаев будет достаточно сказать своими словами, что такое декоратор, и написать простейший код.</p>
10
<p><strong>Вслух:</strong></p>
10
<p><strong>Вслух:</strong></p>
11
<p>- Декоратор, если в двух словах, это функция, которая добавляет новую функциональность к другой функции без изменения её кода. Он как бы оборачивает, декорирует функцию, тем самым расширяя её возможности.</p>
11
<p>- Декоратор, если в двух словах, это функция, которая добавляет новую функциональность к другой функции без изменения её кода. Он как бы оборачивает, декорирует функцию, тем самым расширяя её возможности.</p>
12
<p><strong>Пример кода:</strong></p>
12
<p><strong>Пример кода:</strong></p>
13
<p>Функция<em>say_hi</em>(пример<a>отсюда</a>), которую мы "обернём" в декоратор, возвращает строку "всем привет". Обратите внимание: не печатает, а возвращает.</p>
13
<p>Функция<em>say_hi</em>(пример<a>отсюда</a>), которую мы "обернём" в декоратор, возвращает строку "всем привет". Обратите внимание: не печатает, а возвращает.</p>
14
def say_hi(): return 'всем привет'<p>А наш декоратор превратит символы этой строки из строчных в прописные. Этой возможности у функции<em>say_hi</em>раньше не было, а теперь будет.</p>
14
def say_hi(): return 'всем привет'<p>А наш декоратор превратит символы этой строки из строчных в прописные. Этой возможности у функции<em>say_hi</em>раньше не было, а теперь будет.</p>
15
<p>Пишем декоратор:</p>
15
<p>Пишем декоратор:</p>
16
def uppercase_decorator(function): def wrapper(): func = function() make_uppercase = func.upper() return make_uppercase return wrapper<p>Что здесь происходит - разбираем код построчно:</p>
16
def uppercase_decorator(function): def wrapper(): func = function() make_uppercase = func.upper() return make_uppercase return wrapper<p>Что здесь происходит - разбираем код построчно:</p>
17
<ul><li><strong>В первой строке</strong>мы указываем имя декоратора и то, что он принимает<em>function</em>в качестве своей переменной.</li>
17
<ul><li><strong>В первой строке</strong>мы указываем имя декоратора и то, что он принимает<em>function</em>в качестве своей переменной.</li>
18
<li><strong>Вторая строка</strong> - это объявление функции-обёртки<em>wrapper ()</em>. Тело обёртки в блоке состоит из трёх строк ниже. Оно как раз и описывает, что именно мы будем делать с функцией, ранее принятой декоратором.</li>
18
<li><strong>Вторая строка</strong> - это объявление функции-обёртки<em>wrapper ()</em>. Тело обёртки в блоке состоит из трёх строк ниже. Оно как раз и описывает, что именно мы будем делать с функцией, ранее принятой декоратором.</li>
19
<li><strong>Третья строка:</strong>записываем входящую переменную<strong>function ()</strong>в локальную переменную<em>func</em>. Здесь "локальная" означает, что она действует только в рамках функции<em>wrapper (</em>).</li>
19
<li><strong>Третья строка:</strong>записываем входящую переменную<strong>function ()</strong>в локальную переменную<em>func</em>. Здесь "локальная" означает, что она действует только в рамках функции<em>wrapper (</em>).</li>
20
<li><strong>Четвёртая строка:</strong>мы применяем к <em>func</em>строковый метод<em>upper</em>и записываем результат в другую локальную переменную<em>make_uppercase</em>.</li>
20
<li><strong>Четвёртая строка:</strong>мы применяем к <em>func</em>строковый метод<em>upper</em>и записываем результат в другую локальную переменную<em>make_uppercase</em>.</li>
21
</ul><p>Больше локальных переменных богу локальных переменных! Конечно, всё это ради понятности и читаемости.</p>
21
</ul><p>Больше локальных переменных богу локальных переменных! Конечно, всё это ради понятности и читаемости.</p>
22
<ul><li><strong>Пятая строка:</strong>функция<em>wrapper ()</em>возвращает переменную<em>make_uppercase</em>, то есть строку от <em>function ()</em>, но уже прописными буквами.</li>
22
<ul><li><strong>Пятая строка:</strong>функция<em>wrapper ()</em>возвращает переменную<em>make_uppercase</em>, то есть строку от <em>function ()</em>, но уже прописными буквами.</li>
23
<li><strong>Последняя строка</strong>: декоратор возвращает нам уже саму функцию<em>wrapper</em>, точнее, результат её работы над функцией<em>function</em>.</li>
23
<li><strong>Последняя строка</strong>: декоратор возвращает нам уже саму функцию<em>wrapper</em>, точнее, результат её работы над функцией<em>function</em>.</li>
24
</ul><p>Как это запустить? Пишем символ @, за ним название декоратора, а объявление функции<em>say_hi</em>переносим на строку под ней:</p>
24
</ul><p>Как это запустить? Пишем символ @, за ним название декоратора, а объявление функции<em>say_hi</em>переносим на строку под ней:</p>
25
@uppercase_decorator def say_hi(): return 'всем привет'<p>Печатаем вывод декорированной функции:</p>
25
@uppercase_decorator def say_hi(): return 'всем привет'<p>Печатаем вывод декорированной функции:</p>
26
<p>Получаем на выходе:</p>
26
<p>Получаем на выходе:</p>
27
<p>Если хочется немного дополнить, вот ещё примеры декораторов.</p>
27
<p>Если хочется немного дополнить, вот ещё примеры декораторов.</p>
28
def logging(func): def log_function_called(): print(f'Вызвана {func}') func() return log_function_called @logging def my_name(): print('Крис') @logging def friends_name(): print('Наруто') my_name() friends_name()<a>Источник</a><p><strong>Что здесь происходит:</strong></p>
28
def logging(func): def log_function_called(): print(f'Вызвана {func}') func() return log_function_called @logging def my_name(): print('Крис') @logging def friends_name(): print('Наруто') my_name() friends_name()<a>Источник</a><p><strong>Что здесь происходит:</strong></p>
29
<p>Декоратор принимает в качестве переменной функцию<em>func</em>. Затем функция-обёртка<em>log_function_called</em>печатает "Вызвана func" и запускает её на выполнение. Функции<em>my_name</em>и<em>friends_name</em>печатают имена Крис и Наруто, а в обёрнутом виде декоратор предваряет их выполнение сообщением об их вызове.</p>
29
<p>Декоратор принимает в качестве переменной функцию<em>func</em>. Затем функция-обёртка<em>log_function_called</em>печатает "Вызвана func" и запускает её на выполнение. Функции<em>my_name</em>и<em>friends_name</em>печатают имена Крис и Наруто, а в обёрнутом виде декоратор предваряет их выполнение сообщением об их вызове.</p>
30
def benchmark(func): import time def wrapper(): start = time.time() func() end = time.time() print('[*] Время выполнения: {} секунд.'.format(end - start)) return wrapper @benchmark def fetch_webpage(): import requests webpage = requests.get('https://skillbox.ru') print(webpage) fetch_webpage()<a>Источник</a><p>Что здесь происходит:</p>
30
def benchmark(func): import time def wrapper(): start = time.time() func() end = time.time() print('[*] Время выполнения: {} секунд.'.format(end - start)) return wrapper @benchmark def fetch_webpage(): import requests webpage = requests.get('https://skillbox.ru') print(webpage) fetch_webpage()<a>Источник</a><p>Что здесь происходит:</p>
31
<p>В объявлении декоратора<em>benchmark</em>мы импортируем библиотеку<em>time</em>. В функции-обёртке<em>wrapper</em>засекаем время в переменную<em>start</em>, затем выполняем полученную декоратором функцию, а после этого фиксируем время в переменную<em>end</em>. Далее печатаем время выполнения, просто отняв от величины<em>end</em>величину<em>start</em>прямо внутри команды<em>print</em>.</p>
31
<p>В объявлении декоратора<em>benchmark</em>мы импортируем библиотеку<em>time</em>. В функции-обёртке<em>wrapper</em>засекаем время в переменную<em>start</em>, затем выполняем полученную декоратором функцию, а после этого фиксируем время в переменную<em>end</em>. Далее печатаем время выполнения, просто отняв от величины<em>end</em>величину<em>start</em>прямо внутри команды<em>print</em>.</p>
32
<p>Сама функция<em>fetch_webpage</em>делает простой GET-запрос на наш сайт. Для этого она импортирует популярную библиотеку<em>requests</em>, записывает в переменную<em>webpage</em>ответ сервера Skillbox на запрос и печатает эту переменную.</p>
32
<p>Сама функция<em>fetch_webpage</em>делает простой GET-запрос на наш сайт. Для этого она импортирует популярную библиотеку<em>requests</em>, записывает в переменную<em>webpage</em>ответ сервера Skillbox на запрос и печатает эту переменную.</p>
33
<p>В обёрнутом виде декоратор "запускает секундомер", функция<em>fetch_webpage</em>делает запрос и печатает ответ, после чего декоратор "выключает секундомер" и печатает время, которое функция потратила на всю эту работу.</p>
33
<p>В обёрнутом виде декоратор "запускает секундомер", функция<em>fetch_webpage</em>делает запрос и печатает ответ, после чего декоратор "выключает секундомер" и печатает время, которое функция потратила на всю эту работу.</p>
34
<p>Если хотите произвести впечатление, то можно добавить, что:</p>
34
<p>Если хотите произвести впечатление, то можно добавить, что:</p>
35
<ul><li>Декоратор - это паттерн проектирования (design pattern) в Python, а также функция второго уровня, то есть принимающая другие функции в качестве переменных и возвращающая их.</li>
35
<ul><li>Декоратор - это паттерн проектирования (design pattern) в Python, а также функция второго уровня, то есть принимающая другие функции в качестве переменных и возвращающая их.</li>
36
<li>И в сам декоратор, и в функцию-обёртку можно передать и позиционные, и именованные аргументы - args и kwargs соответственно.</li>
36
<li>И в сам декоратор, и в функцию-обёртку можно передать и позиционные, и именованные аргументы - args и kwargs соответственно.</li>
37
<li>Декораторы работают не только с функциями, но и с классами и методами.</li>
37
<li>Декораторы работают не только с функциями, но и с классами и методами.</li>
38
-
</ul><p>Конечно, ��а собеседовании надо будет пояснить все эти пункты и проиллюстрировать их кодом. На курсе<a>Профессия Python-разработчик</a>вы изучите не только декораторы, но и всё необходимое для того, чтобы с блеском проходить любые собеседования.</p>
38
+
</ul><p>Конечно, на собеседовании надо будет пояснить все эти пункты и проиллюстрировать их кодом. На курсе<a>Профессия Python-разработчик</a>вы изучите не только декораторы, но и всё необходимое для того, чтобы с блеском проходить любые собеседования.</p>
39
<a><b>Бесплатный курс по Python ➞</b>Мини-курс для новичков и для опытных кодеров. 4 крутых проекта в портфолио, живое общение со спикером. Кликните и узнайте, чему можно научиться на курсе. Смотреть программу</a>
39
<a><b>Бесплатный курс по Python ➞</b>Мини-курс для новичков и для опытных кодеров. 4 крутых проекта в портфолио, живое общение со спикером. Кликните и узнайте, чему можно научиться на курсе. Смотреть программу</a>