Как работает область видимости переменных Python? - PullRequest
4 голосов
/ 28 июня 2010

Это хочет, чтобы я глубже копался в источниках Python, но, поскольку на SO есть много людей, которые уже сделали это, я хотел бы услышать их указатели.

>>> import os
>>> def scope():
...     print os
...     import os
... 
>>> scope()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in scope
UnboundLocalError: local variable 'os' referenced before assignment

Мне кажется, что когда синтаксический анализатор интерпретирует файл, он автоматически создает локальную область видимости для функции области видимости, которая делает os "отделенной" от глобальной области видимости.

Это правда? Кто-нибудь хочет указать мне, где я могу найти больше о реализации области?

РЕДАКТИРОВАТЬ: Кроме того, это не особый случай импорта, это работает и для обычных переменных.

Ответы [ 3 ]

5 голосов
/ 28 июня 2010

Когда вы вызываете scope() Python видит, что у вас есть локальная переменная с именем os, используемая внутри вашего метода (из import внутри scope), поэтому она маскирует глобальную os. Однако, когда вы говорите print os, вы еще не достигли строки и не выполнили локальный импорт, поэтому вы видите ошибку относительно ссылки перед назначением. Вот несколько других примеров, которые могут помочь:

>>> x = 3
>>> def printx():
...     print x # will print the global x
...
>>> def printx2():
...     print x # will try to print the local x
...     x = 4
...
>>> printx()
3
>>> printx2()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in printx2
UnboundLocalError: local variable 'x' referenced before assignment

И возвращаясь к вашему os примеру. Любое присвоение os имеет тот же эффект:

>>> os
<module 'os' from 'C:\CDL_INSTALL\install\Python26\lib\os.pyc'>
>>> def bad_os():
...     print os
...     os = "assigning a string to local os"
...
>>> bad_os()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in bad_os
UnboundLocalError: local variable 'os' referenced before assignment

Наконец, сравните эти 2 примера:

>>> def example1():
...     print never_used # will be interpreted as a global
...
>>> def example2():
...     print used_later # will be interpreted as the local assigned later
...     used_later = 42
...
>>> example1()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in example1
NameError: global name 'never_used' is not defined
>>> example2()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in example2
UnboundLocalError: local variable 'used_later' referenced before assignment
1 голос
/ 28 июня 2010

Лексическая область видимости - это обычное явление, и большинство хорошо спроектированных языков, независимо от того, используются ли интерпретированные или скомпилированные, используют ее.

Я не пробовал это некоторое время, но обратите внимание на изящное ключевое слово global и его использование ниже:

o = 1
def foo():
    global o
    o = 2
foo()
print o

Без «глобальной» строки, модификация к o локализована, и «print o» печатает 1. При включенной строке «global o» печатается 2. Мы называем это так, чтомоя функция (без глобального o) выше будет иметь свои собственные переменные.Глобальная вещь, описанная выше, представляет собой способ специально запросить исключение из обычной лексической области видимости.

Истинная лексическая область видимости - это то, чего не хватало в Python 1.0, и что Python имел в течение длительного времени (по крайней мере, если 1.6Я правильно помню).Было только две области: локальная и глобальная, и любые промежуточные области были недоступны.

0 голосов
/ 28 июня 2010

Любая привязка переменной внутри функции делает переменную локальной для этой функции. import, def и class эквивалентны присвоению в этом отношении.

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

См. Учебник по Python для получения дополнительной информации. В частности http://docs.python.org/tutorial/classes.html раздел 9,2

...