Вот забавный ответ.
Вы можете объявить окончательный одноэлементный массив и по-видимому изменить все элементы массива. Я уверен, что это нарушает ту самую причину, по которой это правило компилятора было реализовано в первую очередь, но оно удобно, когда вы находитесь в привязке по времени, как и я был сегодня.
На самом деле я не могу претендовать на кредит для этого. Это была рекомендация IntelliJ! Чувствует себя немного взломанным. Но это не так плохо, как глобальная переменная, поэтому я думал, что стоит упомянуть здесь. Пожалуйста, не голосуйте за мой ответ, если вы не согласны! Это просто решение проблемы. Не обязательно лучший.
final int[] tapCount = {0};
addSiteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tapCount[0]++;
}
});
Python решает ваши переменные с - вообще - тремя доступными пространствами имен.
В любое время во время выполнения есть как минимум три вложенных области, пространства имён которых доступны напрямую: самая внутренняя область поиска, которая сначала выполняется, содержит локальные имена; пространства имен любых закрывающих функций, поиск которых начинается с ближайшей охватывающей области; средняя область поиска, следующая по следующему, содержит глобальные имена текущего модуля; и самая внешняя область (поиск последней) - это пространство имен, содержащее встроенные имена.
Существуют две функции:
globals
иlocals
, которые показывают вам содержимое двух из этих пространств имен.Пространства имен создаются пакетами, модулями, классами, конструкцией объектов и функциями. Других ароматов пространств имен нет.
В этом случае вызов функции с именем
x
должен быть разрешен в локальном пространстве имен или в глобальном пространстве имен.Локальный в этом случае является телом функция метода
Foo.spam
.Глобальный - это хорошо глобальный.
Правило состоит в том, чтобы искать вложенные локальные пространства, созданные функциями метода (и определениями вложенных функций), а затем искать глобальные. Вот и все.
Нет других областей. Оператор
for
(и другие составные операторы, такие какif
иtry
) не создают новые вложенные области. Только определения (пакеты, модули, функции, классы и экземпляры объектов.)Внутри определения класса имена являются частью пространства имен классов.
code2
, например, должно быть квалифицировано именем класса. ОбычноFoo.code2
. Тем не менее,self.code2
также будет работать, потому что объекты Python смотрят на содержащийся класс как на обратную сторону.Объект (экземпляр класса) имеет переменные экземпляра. Эти имена находятся в пространстве имен объекта. Они должны быть квалифицированы объектом. (
variable.instance
.)Из метода класса вы имеете локальные и глобальные переменные. Вы говорите
self.variable
, чтобы выбрать экземпляр как пространство имен. Вы заметите, чтоself
является аргументом для каждой функции-члена класса, делая его частью локального пространства имен.См. Правила области Python , Область Python , Диапазон переменных .
Не было никакого тщательного ответа относительно времени 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
искать функцию во встроенных функциях.
Где x найдено?
blockquote>x не найден, так как вы его не определили. :-) Его можно найти в code1 (global) или code3 (local), если вы его поместили.
code2 (члены класса) не видны для кода внутри методов одного и того же класса - вы бы обычно получают доступ к ним, используя себя. code4 / code5 (петли) живут в той же области, что и для кода3, поэтому, если вы написали на x, вы бы изменили экземпляр x, определенный в коде3, не создавая новый x.
Python статически охвачен , поэтому, если вы передадите «спам» другой функции, спам по-прежнему будет иметь доступ к глобальным переменным в модуле, из которого он пришел (определен в коде1), и в любых других областях (см. ниже). члены code2 будут снова доступны через self.
lambda ничем не отличается от def. Если у вас есть лямбда, используемая внутри функции, это то же самое, что и определение вложенной функции. В Python 2.2 и далее доступны вложенные области. В этом случае вы можете связывать x на любом уровне вложенности функций, а Python будет извлекать самый внутренний экземпляр:
x= 0 def fun1(): x= 1 def fun2(): x= 2 def fun3(): return x return fun3() return fun2() print fun1(), x 2 0
fun3 видит экземпляр x из ближайшей содержащей области, которая является областью функции, связанной с fun2. Но другие x-экземпляры, определенные в fun1 и глобально, не затрагиваются.
До nested_scopes - в Python pre-2.1 и в 2.1, если вы специально не запрашиваете эту функцию с использованием from-future-import - fun1 и fun2 не видны fun3, поэтому ответ S.Lott имеет место, и вы получите глобальный x:
0 0
По сути, единственное, что в Python, которое вводит новую область видимости, - это определение функции. Классы - это немного особый случай, когда все, что определено непосредственно в теле, помещается в пространство имен класса, но они не доступны непосредственно из методов (или вложенных классов), которые они содержат.
В вашем Например, есть только 3 области, где x будет искать в:
Больше областей появляется только при введении вложенной функции (или лямбда) в изображение. Они будут вести себя так, как вы ожидали. Вложенная функция может получить доступ ко всем в локальной области, а также к любой области приложения. например,
def foo():
x=4
def bar():
print x # Accesses x from foo's scope
bar() # Prints 4
x=5
bar() # Prints 5
Ограничения:
Доступ к переменным в областях, отличных от переменных локальной функции, но не может отскочить к новым параметрам без дальнейшего синтаксиса. Вместо этого назначение создает новую локальную переменную вместо того, чтобы влиять на переменную в родительской области. Например:
global_var1 = []
global_var2 = 1
def func():
# This is OK: It's just accessing, not rebinding
global_var1.append(4)
# This won't affect global_var2. Instead it creates a new variable
global_var2 = 2
local1 = 4
def embedded_func():
# Again, this doen't affect func's local1 variable. It creates a
# new local variable also called local1 instead.
local1 = 5
print local1
embedded_func() # Prints 5
print local1 # Prints 4
Чтобы действительно изменить привязки глобальных переменных из области видимости функции, вам нужно указать, что переменная глобальна с ключевым словом global. Например:
global_var = 4
def change_global():
global global_var
global_var = global_var + 1
В настоящее время нет способа сделать то же самое для переменных в приложении областей function , но Python 3 вводит новое ключевое слово «nonlocal
», которое будет действуют аналогично глобальным, но для вложенных областей функций.
Правила обзора для Python 2.x уже изложены в других ответах. Единственное, что я хотел бы добавить, это то, что в Python 3.0 существует также концепция нелокальной области (обозначается ключевым словом «нелокальное»).
EDIT: Здесь PEP . EDIT: здесь
Немного более полный пример области:
from __future__ import print_function # for python 2 support
x = 100
print("1. Global x:", x)
class Test(object):
y = x
print("2. Enclosed y:", y)
x = x + 1
print("3. Enclosed x:", x)
def method(self):
print("4. Enclosed self.x", self.x)
print("5. Global x", x)
try:
print(y)
except NameError as e:
print("6.", e)
def method_local_ref(self):
try:
print(x)
except UnboundLocalError as e:
print("7.", e)
x = 200 # causing 7 because has same name
print("8. Local x", x)
inst = Test()
inst.method()
inst.method_local_ref()
Выход :
1. Global x: 100
2. Enclosed y: 100
3. Enclosed x: 101
4. Enclosed self.x 101
5. Global x 100
6. global name 'y' is not defined
7. local variable 'x' referenced before assignment
8. Local x 200
method
и method_local_ref
должны быть выделены. method
может получить доступ к глобальной переменной и распечатать ее, как в 5. Global x
. Но method_local_ref
не может, потому что позже он определяет локальную переменную с тем же именем. Вы можете проверить это, удалив строку x = 200
и увидите разницу
– kiril
9 September 2016 в 10:35
Python has two namespaces available. Global and local-to-something.
– Rizwan Kassim 16 November 2008 в 01:56code2
. Это не переменная и является атрибутом class / instance. Это правильно. – Lakshman Prasad 5 June 2009 в 13:39Foo
и может быть доступен из любой области с доступом кFoo
сFoo.code2
или изнутриFoo
с тем же синтаксисом. Но я еще не уверен, где это входит в мнемонику LEGB. – Conrad.Dean 24 March 2012 в 17:51global(var_name)
синтаксически неверен. Правильный синтаксис будетglobal var_name
без круглых скобок. Однако у вас есть действительная точка. – martineau 24 December 2012 в 23:48y
записывается и нет объявленийglobal y
- см. Комментарий @ Peter. – martineau 6 August 2013 в 20:19