Какова область действия переменной, инициализированной в операторе if?
Я новичок в Python, так что это, вероятно, простой вопрос. Следующий код в файле (модуле) Python меня немного смущает:
if __name__ == '__main__':
x = 1
print x
На других языках, на которых я работал, этот код выдает исключение, так как x
переменная является локальной для if
заявление и не должно существовать вне его. Но этот код выполняется и печатает 1. Кто-нибудь может объяснить это поведение? Все переменные, созданные в модуле, глобальны / доступны для всего модуля?
7 ответов
Переменные Python ограничены самой внутренней функцией, классом или модулем, в котором они назначены. Блоки управления, такие как if
а также while
блоки не учитываются, поэтому переменная, назначенная внутри if
все еще ограничен функцией, классом или модулем.
(Неявные функции, определенные выражением генератора или списком / набором / диктом , имеют значение, как и лямбда-выражения. Вы не можете вставить оператор присваивания ни в один из них, кроме лямбда-параметров и for
цели предложения являются неявным присваиванием.)
Да, они находятся в одной и той же "локальной области видимости", и на самом деле такой код распространен в Python:
if condition:
x = 'something'
else:
x = 'something else'
use(x)
Обратите внимание, что x
не объявляется или не инициализируется до условия, как, например, в C или Java.
Другими словами, Python не имеет областей действия на уровне блоков. Будьте осторожны с примерами, такими как
if False:
x = 3
print(x)
который явно поднимет NameError
исключение.
Область действия в python следует этому порядку:
Поиск в локальной области
Поиск в объеме любых вмещающих функций
Поиск в глобальном масштабе
Поиск встроенных модулей
( источник)
Заметить, что if
и другие циклические / ветвящиеся конструкции не перечислены - только классы, функции и модули обеспечивают область видимости в Python, поэтому все, что объявлено в if
блок имеет ту же область видимости, что и все, что объявлено вне блока. Переменные не проверяются во время компиляции, поэтому другие языки выдают исключение. В python, пока переменная существует в то время, когда вы в ней нуждаетесь, исключение не будет выдано.
В отличие от языков, таких как C, переменная Python находится в области действия всей функции (или класса, или модуля), где она появляется, а не только в самом внутреннем "блоке". Это как если бы вы заявили int x
в верхней части функции (или класса, или модуля), за исключением того, что в Python вам не нужно объявлять переменные.
Обратите внимание, что существование переменной x
проверяется только во время выполнения - то есть, когда вы добираетесь до print x
заявление. Если __name__
не равно "__main__"
тогда вы получите исключение: NameError: name 'x' is not defined
,
Как сказал Илай, Python не требует объявления переменных. В Си вы бы сказали:
int x;
if(something)
x = 1;
else
x = 2;
но в Python объявление неявное, поэтому, когда вы присваиваете x, оно объявляется автоматически. Это потому, что Python динамически типизирован - он не будет работать на статически типизированном языке, потому что в зависимости от используемого пути переменная может использоваться без объявления. Это будет обнаружено во время компиляции на статически типизированном языке, но с динамически типизированным языком это разрешено.
Единственная причина, по которой статически типизированный язык ограничен объявлением переменных за пределами if
заявления в из-за этой проблемы. Охватите динамику!
Да. Это также верно для for
объем. Но не функции, конечно.
В вашем примере: если условие в if
утверждение ложно, x
не будет определяться, хотя.
Поэтому вы выполняете этот код из командной строки 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
И обратите внимание, что, поскольку типы Python проверяются только во время выполнения, вы можете иметь такой код, как:
if True:
x = 2
y = 4
else:
x = "One"
y = "Two"
print(x + y)
Но мне сложно придумать другие способы работы кода без ошибок из-за проблем с типом.