Какова область действия переменной, инициализированной в операторе if? - PullRequest
225 голосов
/ 13 мая 2010

Я новичок в Python, так что это, вероятно, простой вопрос. Следующий код в файле (модуле) Python меня немного смущает:

if __name__ == '__main__':
    x = 1

print x

В других языках, с которыми я работал, этот код выдает исключение, поскольку переменная x является локальной для оператора if и не должна существовать вне его. Но этот код выполняется и печатает 1. Кто-нибудь может объяснить это поведение? Все переменные, созданные в модуле, глобальны / доступны для всего модуля?

Ответы [ 7 ]

237 голосов
/ 13 мая 2010

Переменные Python ограничены самой внутренней функцией, классом или модулем, в котором они назначены. Блоки управления, такие как if и while, не учитываются, поэтому переменная, назначенная внутри if, по-прежнему находится в области видимости для функции, класса или модуля.

(Неявные функции, определенные выражением генератора или пониманием list / set / dict do count, как и лямбда-выражения. Вы не можете вставить оператор присваивания ни в один из них, кроме параметров лямбда и for цели предложения являются неявным присваиванием.)

76 голосов
/ 13 мая 2010

Да, они находятся в одной и той же «локальной области», и фактически код, подобный этому, распространен в Python:

if condition:
  x = 'something'
else:
  x = 'something else'

use(x)

Обратите внимание, что x не объявляется или не инициализируется перед условием, как, например, в C или Java.

Другими словами, Python не имеет областей действия на уровне блоков. Будьте осторожны с примерами типа

if False:
    x = 3
print(x)

, что явно вызовет NameError исключение.

34 голосов
/ 13 мая 2010

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

  • Поиск в локальной области действия

  • Поиск в объеме любых включающих функций

  • Поиск в глобальном масштабе

  • Поиск встроенных элементов

(* 1 021 * источник * * тысяча двадцать две) * * 1 023

Обратите внимание, что if и другие циклические / ветвящиеся конструкции не перечислены - только классы, функции и модули обеспечивают область видимости в Python, поэтому все, что объявлено в блоке if, имеет ту же область, что и все, что объявлено вне блока. Переменные не проверяются во время компиляции, поэтому другие языки выдают исключение. В python, пока переменная существует в то время, когда она вам требуется, исключение не будет выдано.

9 голосов
/ 13 мая 2010

В отличие от языков, таких как C, переменная Python находится в области действия всей функции (или класса, или модуля), где она появляется, а не только в самом внутреннем «блоке». Вы как будто объявили int x в верхней части функции (или класса, или модуля), за исключением того, что в Python вам не нужно объявлять переменные.

Обратите внимание, что существование переменной x проверяется только во время выполнения - то есть, когда вы попадаете в оператор print x. Если __name__ не равно "__main__", вы получите исключение: NameError: name 'x' is not defined.

9 голосов
/ 13 мая 2010

Как сказал Илай, Python не требует объявления переменных. В Си вы бы сказали:

int x;
if(something)
    x = 1;
else
    x = 2;

но в Python объявление неявное, поэтому при назначении x оно объявляется автоматически. Это потому, что Python динамически типизирован - он не будет работать на статически типизированном языке, потому что в зависимости от используемого пути переменная может использоваться без объявления. Это может быть обнаружено во время компиляции на статически типизированном языке, но с динамически типизированным языком это разрешено.

Единственная причина, по которой статически типизированный язык ограничен необходимостью объявлять переменные вне операторов if из-за этой проблемы. Охватите динамику!

3 голосов
/ 13 мая 2010

Да. Это также верно для for объема. Но не функции, конечно.

В вашем примере: если условие в операторе if ложно, то x не будет определено

2 голосов
/ 13 мая 2010

вы выполняете этот код из командной строки, поэтому if условия имеет значение true и x установлено. Для сравнения:

>>> if False:
    y = 42


>>> y
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    y
NameError: name 'y' is not defined
...