
Понимание нюансов пространств имен и областей действия Python часто бывает полезным для принятия мудрых решений при написании продвинутого Python. Python - настолько дружелюбный язык, что позволяет легко нарушать правила и при этом достигать наших целей. Но иногда правила, нарушенные в прошлом, могут вернуться и укусить нас в будущем невообразимым образом.
Пространства имён
Пространство имен - это отображение между именами переменных и объектами. Существует 3 основных типа пространств имен:
- Пространства имен __main__ и builtins - здесь находятся все встроенные имена, и это пространство имен создается при запуске интерпретатора.
- Global пространство имен - здесь находятся все имена, объявленные с помощью ключевого слова global.
- Локальное пространство имен - сюда относятся локальные переменные, объявленные в модуле или функции.
Сфера
Область действия - это текстовая область программы Python, в которой непосредственно доступно пространство имен. Любая прямая ссылка на имя в области видимости напрямую просматривается в пространстве имен, к которому имеет доступ.
Поиск по имени
Когда выполняется код Python, поиск имени происходит в этом порядке
- Локально - поиск имени в локальном пространстве имен функции.
- Включение - если его нет в локальном пространстве имен, найдите его в области действия функции включения.
- Global - если его там нет, выполните поиск в глобальном пространстве имен текущего модуля.
- Main - если его нет в global, выполните поиск во встроенных пространствах имен и __main__.
нелокальные и глобальные ключевые слова
В Python есть два специальных ключевых слова
- global - Любая переменная с глобальным префиксом связывает эту переменную с глобальным пространством имен
- нелокальный - любая переменная с нелокальным префиксом привязывает переменную к области видимости, которая включает локальную область видимости, но внутреннюю и глобальную. Или, другими словами, размах между глобальным и локальным.
def scope_test():
def do_local():
spam = "local spam" ## Local scope
def do_nonlocal():
nonlocal spam
spam = "nonlocal spam" ## Enclosing scope
def do_global():
global spam
spam = "global spam" ## Global scope
spam = "test spam"
do_local()
print("After local assignment:", spam)
do_nonlocal()
print("After nonlocal assignment:", spam)
do_global()
print("After global assignment:", spam)
scope_test()
print("In global scope:", spam)
Выход выглядит так:
After local assignment: test spam After nonlocal assignment: nonlocal spam After global assignment: nonlocal spam In global scope: global spam
Как видно из примера, «локальный спам» понятен. «Нелокальный спам» привязан к области действия метода def scope_test (). Таким образом, даже после вызова do_global () мы по-прежнему видим «нелокальный спам», потому что выполнение останавливается на шаге 3 (из алгоритма поиска по имени выше) после того, как он находит именной спам.