Грунтовної відповіді щодо часу Python3 не було, тому я тут зробив відповідь. Більшість того, що описано тут, детально описано у розділі 4.2.2 Роздільна здатність імен документації Python 3.
Як передбачено в інших відповідях, існують 4 основні сфери, LEGB - для локальних, закритих, глобальних та вбудованих. Окрім них, існує особливий спектр, орган класу , який не містить вкладеної області для методів, визначених у класі; будь-які призначення в тілі класу роблять змінну звідти на зв'язаною в тілі класу.
Тим більше, жодного блокового твердження, окрім def
іclass
створює змінну область. У Python 2 розуміння списку не створює змінної області, однак у Python 3 змінна циклу в межах розуміння списку створюється в новій області.
Продемонструвати особливості корпусу класу
x = 0
class X(object):
y = x
x = x + 1 # x is now a variable
z = x
def method(self):
print(self.x) # -> 1
print(x) # -> 0, the global x
print(y) # -> NameError: global name 'y' is not defined
inst = X()
print(inst.x, inst.y, inst.z, x) # -> (1, 0, 1, 0)
Таким чином, на відміну від функції функції, ви можете перепризначити змінну на те саме ім'я в тілі класу, щоб отримати змінну класу з тим самим іменем; подальший пошук цього імені вирішує замість змінної класу.
Одне з найбільших сюрпризів для багатьох новачків Python - це те, що for
цикл не створює змінної області. У Python 2 розуміння списку також не створюють сфери застосування (в той час як генератори та диктують розуміння!) Натомість вони просочують значення у функції або глобальній області застосування:
>>> [ i for i in range(5) ]
>>> i
4
Зрозуміння можуть бути використані як хитрий (або жахливий, якщо ви хочете) спосіб внесення змінних змінних в лямбда-виразах у Python 2 - вираз лямбда створює змінну область, як і у def
заяві, але в межах лямбда жодні заяви не дозволені. Призначення, що є висловлюванням в Python, означає, що не допускаються призначення змінних у лямбда, але розуміння списку - це вираз ...
Така поведінка була зафіксована в Python 3 - ніякі вираження розуміння чи генератори не протікають змінними.
Глобальний справді означає область модуля; основним модулем пітона є __main__
; всі імпортовані модулі доступні через sys.modules
змінну; отримати доступ до __main__
одного можна використовувати sys.modules['__main__']
, або import __main__
; цілком прийнятно отримати доступ та призначити там атрибути; вони відображатимуться як змінні у глобальній області основного модуля.
Якщо ім’я коли-небудь присвоюється в поточному діапазоні (крім сфери класу), воно вважатиметься приналежним до цього діапазону, інакше вважатиметься приналежним до будь-якого вкладеного області, що присвоює змінній (можливо, вона не буде призначена все ж, або зовсім не), або, нарешті, глобальний розмах. Якщо змінна вважається локальною, але вона ще не встановлена або була видалена, то читання значення змінної призведе до UnboundLocalError
, що є підкласом NameError
.
x = 5
def foobar():
print(x) # causes UnboundLocalError!
x += 1 # because assignment here makes x a local variable within the function
# call the function
foobar()
Область може заявити, що вона явно хоче змінити глобальну змінну (область модуля) за допомогою глобального ключового слова:
x = 5
def foobar():
global x
print(x)
x += 1
foobar() # -> 5
print(x) # -> 6
Це також можливо, навіть якщо воно було затінене в області застосування:
x = 5
y = 13
def make_closure():
x = 42
y = 911
def func():
global x # sees the global value
print(x, y)
x += 1
return func
func = make_closure()
func() # -> 5 911
print(x, y) # -> 6 13
У python 2 не існує простого способу змінити значення в області, що додається; зазвичай це моделюється за допомогою змінного значення, такого як список довжиною 1:
def make_closure():
value = [0]
def get_next_value():
value[0] += 1
return value[0]
return get_next_value
get_next = make_closure()
print(get_next()) # -> 1
print(get_next()) # -> 2
Однак у python 3 nonlocal
на допомогу приходить:
def make_closure():
value = 0
def get_next_value():
nonlocal value
value += 1
return value
return get_next_value
get_next = make_closure() # identical behavior to the previous example.
nonlocal
Документація каже , що
Імена, перелічені в нелокальному твердженні, на відміну від перелічених у глобальній заяві, повинні посилатися на раніше існуючі прив'язки в обкладинці (область, у якій має бути створена нова прив'язка, не може бути визначена однозначно).
тобто nonlocal
завжди посилається на найпотужнішу зовнішню неглобальну область, де ім'я було пов'язане (тобто присвоєне, в тому числі використовується як for
цільова змінна, у with
пункті або як функціональний параметр).
Будь-яка змінна, яка не вважається локальною для поточного обсягу, або будь-яка охоплює область, є глобальною змінною. У глобальному словнику модуля знайдено глобальне ім'я; якщо його не знайдено, глобальний слід шукати з вбудованого модуля; назву модуля було змінено з python 2 на python 3; у python 2 це було, __builtin__
а в python 3 зараз його називають builtins
. Якщо ви призначите атрибут вбудованого модуля, його буде видно після цього будь-який модуль як читабельну глобальну змінну, якщо тільки цей модуль не затінює їх власною глобальною змінною з тим же ім'ям.
Читання вбудованого модуля також може бути корисним; припустимо, що ви хочете функцію друку в стилі python 3 в деяких частинах файлу, але інші частини файлу все ще використовують print
оператор. У Python 2.6-2.7 ви можете отримати функцію Python 3 за print
допомогою:
import __builtin__
print3 = __builtin__.__dict__['print']
from __future__ import print_function
Фактично не імпортує print
функції ніде в Python 2 - замість цього він просто відключає правил синтаксичного аналізу для print
затвердження в поточному модулі, обробки , print
як і будь-який інший ідентифікатор змінної, і , таким чином , дозволяючи print
функції розглядати в вбудованих команд.