在if语句中初始化的变量范围是什么?
这可能是一个简单的作用域问题。下面这段代码在一个Python文件(模块)中让我有点困惑:
if __name__ == '__main__':
x = 1
print x
在我之前使用过的其他编程语言中,这段代码会抛出一个异常,因为x
这个变量是局部的,只在if
语句内部存在,外面是不能用的。但是这段代码却能正常执行,并且打印出1。有没有人能解释一下这种行为?模块中创建的所有变量都是全局的,能在整个模块中使用吗?
7 个回答
48
在Python中,作用域的查找顺序是这样的:
先查找本地作用域
再查找任何封闭函数的作用域
接着查找全局作用域
最后查找内置作用域
(来源)
注意,if
语句和其他循环或分支结构并不提供作用域 - 只有类、函数和模块才会提供作用域。所以在if
块中声明的任何东西,其作用域和在块外声明的东西是一样的。变量在编译时并不会被检查,这就是为什么其他语言会抛出异常的原因。在Python中,只要在你需要这个变量的时候它存在,就不会抛出异常。
172
是的,它们在同一个“局部作用域”里,实际上这样的代码在Python中很常见:
if condition:
x = 'something'
else:
x = 'something else'
use(x)
注意,x
在条件之前并没有像C或Java那样被声明或初始化。
换句话说,Python没有块级作用域。不过,要小心像下面这样的例子:
if False:
x = 3
print(x)
这会明显引发一个NameError
错误。
516
在Python中,变量的作用范围是由它们被定义的最内层的函数、类或模块决定的。像if
和while
这样的控制块不算在内,所以如果你在一个if
语句里面定义了一个变量,它的作用范围还是在那个函数、类或模块里。
(不过,通过生成器表达式或者列表/集合/字典推导式定义的隐式函数是算在内的,lambda表达式也是如此。虽然你不能在这些地方直接写赋值语句,但lambda的参数和for
语句中的目标是隐式赋值。)