Не было никакого подробного ответа относительно времени Python3, поэтому я сделал ответ здесь.
Как указано в других ответах, есть 4 основных области, LEGB, для Local, Enclosing, Global и Builtin. В дополнение к ним существует специальная область видимости, тело класса , которая не содержит включающей области видимости для методов, определенных в классе; любые присваивания в теле класса приводят к тому, что переменная будет связана в теле класса.
В частности, оператор блока no , кроме 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 понимание списка также не создает область действия (в то время как генераторы и вычисления dict делают это!) Вместо этого они пропускают значение в функции или глобальной области видимости:
>>> [ i for i in range(5) ]
>>> i
4
Понимания могут использоваться как хитрый (или ужасный, если хотите) способ создания изменяемых переменных в лямбда-выражениях в Python 2 - лямбда-выражение создает переменную область видимости, как это делает оператор def
, но внутри лямбда-выражения заявления не допускаются. Назначение, являющееся оператором в Python, означает, что никакие переменные назначения в лямбде не допускаются, но понимание списка является выражением ...
Это поведение было исправлено в Python 3 - нет выражений понимания или генераторов утечек переменных.
Глобальный действительно означает область видимости модуля; основным модулем Python является __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()
Область может объявить, что она явно хочет изменить глобальную переменную (область видимости модуля) с ключевым словом global:
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.
Любая переменная, которая не считается локальной для текущей области или любой включающей области, является глобальной переменной. Глобальное имя ищется в глобальном словаре модуля; если он не найден, глобальный объект ищется из встроенного модуля; название модуля было изменено с python 2 на python 3; в питоне 2 он был __builtin__
, а в питоне 3 он теперь называется builtins
. Если вы назначите атрибут встроенного модуля, он будет виден после этого любому модулю как читаемая глобальная переменная, если только этот модуль не затеняет их своей глобальной переменной с тем же именем.
Чтение встроенного модуля также может быть полезно; Предположим, что вам нужна функция печати в стиле Python 3 в некоторых частях файла, но в других частях файла все еще используется оператор print
. В Python 2.6-2.7 вы можете получить функцию Python 3 print
с помощью:
import __builtin__
print3 = __builtin__.__dict__['print']
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * from __future__ import print_function
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *1066* * * * * * * * '' '' * ”] *1066* На самом деле *1066* фактически не импортирует функцию print
в любом месте Python 2 - вместо этого он просто отключает правила синтаксического анализа для оператора print
в текущем модуле, обрабатывая print
, как любой другой идентификатор переменной, и, таким образом, разрешение функции print
для поиска во встроенных функциях.