ChatGPT解决这个技术问题 Extra ChatGPT

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

我是 Python 新手,所以这可能是一个简单的范围界定问题。 Python文件(模块)中的以下代码让我有些困惑:

if __name__ == '__main__':
    x = 1

print x

在我使用过的其他语言中,此代码会引发异常,因为 x 变量是 if 语句的本地变量,不应存在于它之外。但是这段代码执行,并打印出 1。谁能解释这种行为?模块中创建的所有变量是否对整个模块都是全局的/可用的?

您可能不知道的另一个怪癖:如果上面的 if 语句不成立(即 __name__not '__main__',例如当您导入模块而不是执行它时top-level),那么 x 将永远不会被绑定,随后的 print x 语句将抛出 NameError: name 'x' is not defined

u
user2357112

Python 变量的作用域是分配它们的最里面的函数、类或模块。像 ifwhile 块这样的控制块不计算在内,因此在 if 内分配的变量仍然作用于函数、类或模块。

(由生成器表达式或 list/set/dict 理解 do 定义的隐式函数计数,就像 lambda 表达式一样。您不能将赋值语句填充到其中任何一个中,但 lambda 参数和 for子句目标是隐式赋值。)


感谢您的回答。我已经用 python 编码多年了,直到现在才明白这一点。知道这一点确实会让事情变得更容易。我总是发现 python 处理范围的方式有时是一种骗局。
n
nbro

是的,它们在同一个“本地范围”内,实际上这样的代码在 Python 中很常见:

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

use(x)

请注意,x 没有在条件之前声明或初始化,例如在 C 或 Java 中。

换句话说,Python 没有块级作用域。但是要小心,例如

if False:
    x = 3
print(x)

这显然会引发 NameError 异常。


我掉进了if False:的陷阱。
D
Daniel G

python中的范围遵循以下顺序:

搜索本地范围

搜索任何封闭函数的范围

搜索全局范围

搜索内置插件

(source)

请注意,未列出 if 和其他循环/分支构造 - 只有类、函数和模块在 Python 中提供范围,因此在 if 块中声明的任何内容都与在该块之外清除的任何内容具有相同的范围。在编译时不检查变量,这就是其他语言抛出异常的原因。在python中,只要变量在你需要的时候存在,就不会抛出异常。


S
Skilldrick

正如 Eli 所说,Python 不需要变量声明。在 C 中你会说:

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

但在 Python 中声明是隐式的,因此当您分配给 x 时,它会自动声明。这是因为 Python 是动态类型的——它不能在静态类型的语言中工作,因为根据所使用的路径,可能会在未声明的情况下使用变量。这将在编译时在静态类型语言中被捕获,但对于动态类型语言,它是允许的。

由于这个问题,静态类型语言仅限于必须在 if 语句之外声明变量的唯一原因。拥抱动态!


P
Paul Stephenson

与 C 等语言不同,Python 变量在其出现的整个函数(或类或模块)的范围内,而不仅仅是在最里面的“块”中。就好像您在函数(或类或模块)的顶部声明了 int x,但在 Python 中您不必声明变量。

请注意,仅在运行时检查变量 x 的存在 - 即,当您到达 print x 语句时。如果 __name__ 不等于 "__main__",那么您会得到一个异常:NameError: name 'x' is not defined


类不创建范围;类中的“局部”变量只是在创建时添加到类的字典中。
O
Olivier Verdier

是的。 for 范围也是如此。但当然不是函数。

在您的示例中:如果 if 语句中的条件为 false,则不会定义 x


S
SilentGhost

您正在从命令行执行此代码,因此 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