Не было никакого тщательного ответа относительно времени Python3, поэтому я сделал здесь ответ.
Как указано в других ответах, есть четыре основных области, LEGB, для Local, Enclosing, Global и Builtin. В дополнение к этим, существует особая область, тело класса, которая не содержит охватывающей области для методов, определенных внутри класса; любые присваивания внутри тела класса делают переменную оттуда связанной с телом в классе.
В частности, никакой блок-оператор, кроме 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()
scope может объявить, что он явно хочет изменить глобальную (область видимости модуля) с глобальным ключевым словом:
x = 5
def foobar():
global x
print(x) # -> 5
x += 1
foobar()
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() # -> print 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.
< hr> Любая переменная, которая не считается локальной для текущей области или любой охватывающей области, является глобальной переменной. Глобальное имя просматривается в глобальном словаре модуля; если он не найден, глобальный отображается с модуля встроенных модулей; имя модуля было изменено с python 2 на python 3; в python 2 это было __builtin__
, а в python 3 теперь называется builtins
. Если вы назначаете атрибут встроенного модуля, после этого он будет отображаться в любом модуле как читаемая глобальная переменная, если только этот модуль не тени их собственной глобальной переменной с тем же именем.
Чтение встроенный модуль также может быть полезен; предположим, что вы хотите использовать функцию печати в стиле python 3 в некоторых частях файла, но в других частях файла по-прежнему используется оператор print
, если ваша версия python равна> = 2.6, вы можете получить новую функцию стиля как:
import __builtin__
print3 = __builtin__.__dict__['print']
На самом деле from __future__ import print_function
не импортирует функцию print
в любом месте Python 2, вместо этого он просто отключает правила синтаксического анализа для оператора print
в текущем модуле, обрабатывая print
, как и любую другую переменную Идентификатор и, таким образом, позволяет print
искать функцию во встроенных функциях.