Не было никакого тщательного ответа относительно времени Python3, поэтому я сделал здесь ответ.
Как указано в других ответах, существует 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 - нет выражений понимания или переменных утечки генераторов.
Глобальное на самом деле означает объем модуля; основным модулем python является __main__
; все импортированные модули доступны через переменную sys.modules
; для получения доступа к __main__
можно использовать sys.modules['__main__']
, или import __main__
; вполне приемлемо для доступа и назначения атрибутов; они будут отображаться как переменные в глобальной области основного модуля.
Если имя когда-либо назначается в текущей области (за исключением объема класса), то он будет считаться принадлежащим к этой области действия, в противном случае он будет считаться с принадлежностью к какой-либо области видимости, что сопоставляет переменная (она может еще не назначена или вообще отсутствует) или, наконец, глобальная область. Если переменная считается локальной, но она еще не установлена или была удалена, чтение значения переменной приведет к UnboundLocalError
, который является подклассом NameError
.
x = 5
def foobar()
print(x) # UnboundLocalError!
x += 1 # assignment here makes x a local variable!
Область может заявить, что она явно хочет изменить глобальную переменную (модуль сфера), с глобальным ключевым словом:
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.
любых переменный, не считается локальным для текущей области или любой охватывающей области, является глобальной переменной. Глобальное имя просматривается в глобальном словаре модуля; если он не найден, глобальный отображается с модуля встроенных модулей; имя модуля было изменено с 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
будет искать в встроенных функциях.
люди могли прекратить делать небольшие "кармы изменения" на этот вопрос, пожалуйста? – 2017-03-24 19:53:10
Они не все «редактирование кармы». Некоторые из них потому, что люди не понимают, как все работает. См. [** _ Если вопросы включают «теги» в их названиях? _ **] (https://meta.stackexchange.com/questions/19190/should-questions-include-tags-in-their-titles). – martineau 2017-04-23 03:10:13