"локальная переменная, на которую ссылаются до назначения" - только функции?
Возьмите следующий код:
import something
def Foo():
something = something.SomeClass()
return something
... это, по-видимому, недействительный код:
UnboundLocalError: local variable 'something' referenced before assignment
... поскольку локальная переменная something
создается, но не назначается, прежде чем оценивается RHS =
. (См., Например, этот связанный ответный комментарий.) Мне это кажется немного странным, но, конечно, я поеду с ним. Теперь, почему следующий допустимый код?
class Foo(object):
something = something.SomeClass()
Мое понимание заключалось в том, что внутреннее определение class
было по существу областью:
Затем класс классов выполняется в новом кадре выполнения (см. раздел "Именование и привязка" ), используя недавно созданное локальное пространство имен и исходное глобальное пространство имен.
Итак, почему этот код действует иначе, чем функция?
Ответы
Ответ 1
Из документации класса python:
Определения классов помещают еще одно пространство имен в локальную область.
Особая причуда Python заключается в том, что - если глобальный оператор не действует, назначения имен всегда переходят во внутреннюю область. Присвоения не копируют данные - они просто связывают имена с объектами. То же самое верно и для делеций: оператор del x удаляет привязку x из пространства имен, на которое ссылается локальная область. Фактически, все операции, которые вводят новые имена, используют локальную область действия: в частности, операторы импорта и определения функций связывают имя модуля или функции в локальной области. (Глобальный оператор можно использовать, чтобы указать, что конкретные переменные живут в глобальной области.)
Таким образом, внутри функции (или области) присваивание создает локальную несвязаемую переменную, к которой обращаются до ее привязки, тогда как в определении класса она создает запись в словаре имен пространства этого класса при назначении, что позволяет разрешение something
во внешнее пространство имен (пространство имен модулей).
Ответ 2
Рассмотрим следующий пример, который может помочь в этом:
import datetime
class Foo(object):
datetime = datetime.datetime
>>> datetime
<module 'datetime' from '/usr/lib/python2.6/lib-dynload/datetime.so'>
>>> Foo.datetime
<type 'datetime.datetime'>
Обратите внимание, что строка datetime = datetime.datetime
фактически назначает имя Foo.datetime
, которое не является двусмысленным с глобальным datetime
(например, было бы, если бы тот же код был в функции).
Таким образом, поскольку определения классов создают новое пространство имен, а также новую область, вам разрешено напрямую обращаться к имени в закрывающей области и назначать одно имя в локальной области.