在if语句中初始化的变量范围是什么?

413 投票
7 回答
214854 浏览
提问于 2025-04-15 22:40

这可能是一个简单的作用域问题。下面这段代码在一个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中,变量的作用范围是由它们被定义的最内层的函数、类或模块决定的。像ifwhile这样的控制块不算在内,所以如果你在一个if语句里面定义了一个变量,它的作用范围还是在那个函数、类或模块里。

(不过,通过生成器表达式或者列表/集合/字典推导式定义的隐式函数是算在内的,lambda表达式也是如此。虽然你不能在这些地方直接写赋值语句,但lambda的参数和for语句中的目标是隐式赋值。)

撰写回答