"локальная переменная, на которую ссылаются до присваивания" - только функции? - PullRequest
11 голосов
/ 01 февраля 2012

Возьмите следующий код:

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 по сути является областью действия:

Затем набор класса выполняется в новом фрейме выполнения (см. Раздел Имена и привязка), используя недавно созданное локальное пространство имен и исходное глобальное пространство имен.

Итак, почему этот код действует иначе, чем код функции?

Ответы [ 2 ]

6 голосов
/ 01 февраля 2012

Из документации по классу Python :

Определения классов помещают еще одно пространство имен в локальную область.

Особая особенность Python заключается в том, что - если не действуют глобальные операторы - присваивания имен всегда входят в самую внутреннюю область. Назначения не копируют данные - они просто привязывают имена к объектам. То же самое верно и для удалений: оператор del x удаляет привязку x из пространства имен, на которое ссылается локальная область. Фактически все операции, которые вводят новые имена, используют локальную область: в частности, операторы импорта и определения функций связывают имя модуля или функции в локальной области. (Глобальный оператор может использоваться для указания того, что конкретные переменные находятся в глобальной области видимости.)

Таким образом, внутри функции (или области видимости) назначение создает локальную несвязанную переменную, доступ к которой осуществляется до ее привязки, тогда как в определении класса она создает запись в словаре «пространства имен» этого класса при назначении, позволяя разрешение something во внешнее пространство имен (пространство имен модуля).

5 голосов
/ 01 февраля 2012

Рассмотрим следующий пример, который может помочь прояснить это:

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(как было бы, если бы в функции был один и тот же код).

В итоге, поскольку определения классов создают новое пространство имен, а также новую область видимости, вам разрешен прямой доступ к имени во внешней области видимости.и назначьте то же имя в локальной области видимости.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...