О декораторах в Python

в 11:32, , рубрики: decorator, python, Блог компании OTUS. Онлайн-образование, декораторы, переменные

Всем привет!
Перевод статьи подготовлен для студентов курса «Web-разработчик на Python». Интересно развиваться в данном направлении? Запишитесь на День Открытых Дверей курса и пообщайтесь вживую с преподавателем: онлайн-трансляция 23 июля в 20:00 по мск.!

О декораторах в Python - 1

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

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

@login_required
def edit_post(post_id):
...

С декораторами очень легко работать, но создание декораторов задача непростая даже для опытных Python-программистов. В этой статье мы с вами рассмотрим пошагово как работают декораторы в Python.

Функции

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

>>> def foo():
...     return 1
...
>>>
>>> foo()
1
>>>

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

>>>
>>> a_string = "This is a global variable"
>>>
>>> def foo():
...     print(locals())
...
>>>
>>> print(globals())
{..., 'a_string': 'This is a global variable'}
>>>
>>> foo() # 2
{}
>>>

Область видимости функции как переменная

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

>>>
>>> a_string = "This is a global variable"
>>>
>>> def foo():
...     print(a_string) #1
...
>>>
>>> foo()
This is a global variable
>>>

Время жизни переменной

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

>>> def foo():
...     x = 1
...
>>> foo()
>>>
>>> print(x) # 1
Traceback (most recent call last):
  ...
NameError: name 'x' is not defined
>>>

Вложенные функции

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

>>>
>>> def outer():
...     x = 1
...     def inner():
...         print(x) # 1
...     inner() # 2
...
>>> outer()
1
>>>

Декораторы

Замыкание (closure), которое принимает функцию в качестве параметра и возвращает функцию, называется декоратором. Рассмотрим пример полезных декораторов.

>>>
>>> def outer(some_func):
...     def inner():
...         print("before some_func")
...         ret = some_func() # 1
...         return ret + 1
...     return inner
...
>>> def foo():
...     return 1
...
>>> decorated = outer(foo) # 2
>>>
>>> decorated()
before some_func
2
>>>

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

>>>
>>> foo = outer(foo)
>>>
>>> foo # doctest: +ELLIPSIS
<function outer.<locals>.inner at 0x...>
>>>

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

Автор: nmonax

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js