我刚接触Python,所以这可能是一个简单的作用域问题。以下Python文件(模块)中的代码让我有点困惑:
if __name__ == '__main__': x = 1 print x
在我使用过的其他语言中,这段代码会抛出异常,因为x变量是if语句的局部变量,不应该存在于if语句之外。但是这段代码执行并输出1。有人能解释一下这种行为吗?在一个模块中创建的所有变量对整个模块都是全局的/可用的吗?
x
if
是的,它们在同一个“局部作用域”中,实际上这样的代码在Python中很常见:
if condition: x = 'something' else: x = 'something else' use(x)
注意,x没有在条件之前声明或初始化,就像在C或Java中那样。
换句话说,Python没有块级作用域。但是,在使用诸如
if False: x = 3 print(x)
这显然会引发NameError异常。
NameError
是的。对于for作用域也是如此。当然不是函数。
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和其他循环/分支结构没有列出-只有类、函数和模块在Python中提供作用域,因此在if块中声明的任何内容都与在块外声明的任何内容具有相同的作用域。在编译时不检查变量,这就是为什么其他语言会抛出异常。在python中,只要变量在你需要它的时候存在,就不会抛出异常。
正如Eli所说,Python不需要变量声明。在C中你会说:
int x; if(something) x = 1; else x = 2;
但在Python中,声明是隐式的,所以当你赋值给x时,它会自动声明。这是因为Python是动态类型的——它在静态类型语言中不起作用,因为根据所使用的路径,变量可能在没有声明的情况下被使用。在静态类型语言中,这将在编译时捕获,但在动态类型语言中,这是允许的。
静态类型语言被限制在if语句之外声明变量的唯一原因就是因为这个问题。拥抱动态!
Python变量的作用域是它们被赋值的最里面的函数、类或模块。像if和while这样的控制块不算数,所以在if中赋值的变量仍然是函数、类或模块的作用域。
while
(生成器表达式或list/set/dict推导式做计数定义的隐式函数,lambda表达式也是如此。你不能把赋值语句塞进这些语句中,但lambda形参和for子句目标是隐式赋值。)
与C等语言不同,Python变量在它出现的整个函数(或类或模块)的范围内,而不仅仅是在最里面的“块”中。这就好像你在函数(或类,或模块)的顶部声明了int x,除了在Python中你不需要声明变量。
int x
注意,变量x的存在只在运行时检查——也就是说,当你得到print x语句时。如果__name__不等于"__main__",则会得到一个异常:NameError: name 'x' is not defined。
print x
__name__
"__main__"
NameError: name 'x' is not defined