Это сообщение немного длинное со многими примерами, но я надеюсь, что это поможет мне и другим лучше понять всю историю переменных и поиск атрибутов в Python 2.7.
Я использую термины PEP 227 (http://www.python.org/dev/peps/pep-0227/) для блоков кода (таких как модули, определение класса, определения функций и т.д.) и привязки переменных (например, назначения, объявления аргументов, класс и объявление функции, для циклов и т.д.)
Я использую термины переменные для имен, которые можно вызывать без точка и атрибуты для имен, которые должны быть квалифицированы с помощью объекта name (например, obj.x для атрибута x объекта obj).
Для Python для всех блоков кода существует три области действия, но функции:
- Local
- Global
- Builtin
Для Python существует только четыре блока для функций (согласно PEP 227):
- Local
- Функции закрытия
- Global
- Builtin
Правило для привязки переменной и ее нахождения в блоке довольно просто:
- любое связывание переменной с объектом в блоке делает эту переменную локально к этому блоку, если переменная не объявлена глобальной (в этом случай, когда переменная принадлежит глобальной области)
- ссылка на переменную просматривается с использованием правила LGB (локального, глобальный, встроенный) для всех блоков, но функции
- ссылка на переменную просматривается с использованием правила LEGB (local, охватывающий, глобальный, встроенный) только для функций.
Дайте мне знать примеры, подтверждающие это правило, и показывающие многие Особые случаи. Для каждого примера я дам свое понимание. пожалуйста исправьте меня, если я ошибаюсь. В последнем примере я не понимаю исход.
пример 1:
x = "x in module"
class A():
print "A: " + x #x in module
x = "x in class A"
print locals()
class B():
print "B: " + x #x in module
x = "x in class B"
print locals()
def f(self):
print "f: " + x #x in module
self.x = "self.x in f"
print x, self.x
print locals()
>>>A.B().f()
A: x in module
{'x': 'x in class A', '__module__': '__main__'}
B: x in module
{'x': 'x in class B', '__module__': '__main__'}
f: x in module
x in module self.x in f
{'self': <__main__.B instance at 0x00000000026FC9C8>}
В классах нет ограничений (правило LGB) и функция в класс не может получить доступ к атрибутам класса, не используя квалифицированное имя (self.x в этом примере). Это хорошо описано в PEP227.
Пример 2:
z = "z in module"
def f():
z = "z in f()"
class C():
z = "z in C"
def g(self):
print z
print C.z
C().g()
f()
>>>
z in f()
z in C
Здесь переменные в функциях просматриваются с использованием правила LEGB, но если класс находится в пути, аргументы класса пропускаются. Снова здесь, это то, что объясняет PEP 227.
Пример 3:
var = 0
def func():
print var
var = 1
>>> func()
Traceback (most recent call last):
File "<pyshell#102>", line 1, in <module>
func()
File "C:/Users/aa/Desktop/test2.py", line 25, in func
print var
UnboundLocalError: local variable 'var' referenced before assignment
Мы ожидаем, что с динамическим языком, таким как python, все будет разрешено динамически. Но это не относится к функциям. Местный переменные определяются во время компиляции. PEP 227 и http://docs.python.org/2.7/reference/executionmodel.html описывают это поведение таким образом
"Если операция привязки имени происходит где угодно внутри блока кода, все использование имени внутри блока рассматривается как ссылка на текущий блок. "
пример 4:
x = "x in module"
class A():
print "A: " + x
x = "x in A"
print "A: " + x
print locals()
del x
print locals()
print "A: " + x
>>>
A: x in module
A: x in A
{'x': 'x in A', '__module__': '__main__'}
{'__module__': '__main__'}
A: x in module
Но мы видим здесь, что это утверждение в PEP227 "Если привязка имени операция выполняется в любом месте внутри кодового блока, все использования имени внутри блока рассматриваются как ссылки на текущий блок. " неправильно, когда блок кода является классом. Более того, для классов, кажется что привязка локального имени не выполняется во время компиляции, но во время выполнение с использованием пространства имен классов. В этом отношении, PEP227 и модель исполнения в документе Python вводит в заблуждение и для некоторые части ошибочны.
Пример 5:
x = 'x in module'
def f2():
x = 'x in f2'
def myfunc():
x = 'x in myfunc'
class MyClass(object):
x = x
print x
return MyClass
myfunc()
f2()
>>>
x in module
мое понимание этого кода следующее. Инструкция x = x сначала найдите объект правой рукой x выражения. к. В этом случае объект просматривается локально в классе, тогда следуя правилу LGB, он просматривается в глобальном масштабе, что строка 'x в модуле'. Тогда локальный атрибут x для MyClass созданный в словаре классов и указывающий на объект string.
пример 6:
Теперь вот пример, который я не могу объяснить. Это очень близко к примеру 5, я просто меняю локальный MyClass атрибут от x до y.
x = 'x in module'
def f2():
x = 'x in f2'
def myfunc():
x = 'x in myfunc'
class MyClass(object):
y = x
print y
return MyClass
myfunc()
f2()
>>>
x in myfunc
Почему в этом случае ссылка x в MyClass просматривается в самая внутренняя функция?