Какова область действия переменной, инициализированной в инструкции if?

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

if __name__ == '__main__':
    x = 1

print x

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

Ответ 1

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

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

Ответ 2

Да, они находятся в одной и той же "локальной области", и на самом деле такой код обычно используется в Python:

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

use(x)

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

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

if False:
    x = 3
print(x)

который явно повысил бы исключение NameError.

Ответ 3

Область в python следует этому порядку:

  • Поиск локальной области

  • Найдите область действия любых закрывающих функций

  • Поиск глобальной области

  • Поиск встроенных модулей

(источник)

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

Ответ 4

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

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

Ответ 5

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

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

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

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

Ответ 6

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

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

Ответ 7

вы выполняете этот код из командной строки, поэтому if условия истинны и 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