Простой Python. Современный стиль программирования (Любанович) - страница 70

>>>> cooler_add_ints(3, 5)

>Running function: add_ints

>Positional arguments: (3, 5)

>Keyword arguments: {}

>Result: 8

>8

В качестве альтернативы мануальному присваиванию декоратора, показанному выше, просто добавьте конструкцию @имя_декоратора перед функцией, которую хотите декорировать:

>>>> @document_it

>… def add_ints(a, b):

>…·····return a + b

>…

>>>> add_ints(3, 5)

>Start function add_ints

>Positional arguments: (3, 5)

>Keyword arguments: {}

>Result: 8

>8

Каждая функция может иметь более одного декоратора. Напишем еще один декоратор, который называется square_it() и возводит результат в квадрат.

>>>> def square_it(func):

>…·····def new_function(*args, **kwargs):

>…·········result = func(*args, **kwargs)

>…·········return result * result

>…·····return new_function

>…

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

>>>> @document_it

>… @square_it

>… def add_ints(a, b):

>…·····return a + b

>…

>>>> add_ints(3, 5)

>Running function: new_function

>Positional arguments: (3, 5)

>Keyword arguments: {}

>Result: 64

>64

Попробуем поменять порядок декораторов:

>>>> @square_it

>… @document_it

>… def add_ints(a, b):

>…·····return a + b

>…

>>>> add_ints(3, 5)

>Running function: add_ints

>Positional arguments: (3, 5)

>Keyword arguments: {}

>Result: 8

>64

Пространства имен и область определения

Имя может ссылаться на несколько разных вещей в зависимости от того, где оно используется. Программы в Python могут иметь разные пространства имен — разделы, внутри которых определенное имя уникально и не связано с такими же именами в других пространствах имен.

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

В основной программе определяется глобальное пространство имен, поэтому переменные, находящиеся в этом пространстве имен, являются глобальными.

Вы можете получить значение глобальной переменной внутри функции:

>>>> animal = 'fruitbat'

>>>> def print_global():

>…·····print('inside print_global:', animal)

>…

>>>> print('at the top level:', animal)

>at the top level: fruitbat

>>>> print_global()

>inside print_global: fruitbat

Но если попробуете получить значение глобальной переменной и изменить его внутри функции, получите ошибку: