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
Но если попробуете получить значение глобальной переменной и изменить его внутри функции, получите ошибку:
>>> def change_and_print_global():
…·····print('inside change_and_print_global:', animal)
…·····animal = 'wombat'
…·····print('after the change:', animal)
…
>>> change_and_print_global()
Traceback (most recent call last):
··File "
··File "
UnboundLocalError: local variable 'animal' referenced before assignment
Если вы просто измените его, изменится другая переменная, которая также называется animal, но находится внутри функции:
>>> def change_local():
…·····animal = 'wombat'
…·····print('inside change_local:', animal, id(animal))
…
>>> change_local()
inside change_local: wombat 4330406160
>>> animal
'fruitbat'
>>> id(animal)
4330390832
Что здесь произошло? В первой строке мы присвоили строку 'fruitbat' глобальной переменной с именем animal. Функция change_local() также имеет переменную с именем animal, но она находится в ее локальном пространстве имен.
Мы использовали функцию id(), чтобы вывести на экран уникальное значение каждого объекта и доказать, что переменная animal, расположенная внутри функции change_local(), — это не переменная animal, расположенная на основном уровне программы.
Чтобы получить доступ к глобальной переменной вместо локальной переменной внутри функции, вам нужно явно использовать ключевое слово global (вы знали, что я это скажу: явное лучше неявного):
>>> animal = 'fruitbat'
>>> def change_and_print_global():
…·····global animal
…·····animal = 'wombat'