这可能是一个简单的作用域问题。下面的代码在Python文件(模块)中让我有点困惑:
if __name__ == '__main__':
x = 1
print x
在我工作过的其他编程语言中,这段代码会抛出异常,因为 x
变量只在 if
语句中存在,不应该在外部存在。但是这段代码执行了,并打印了1。有人能解释一下这种行为吗?在模块中创建的所有变量都是全局的/可用于整个模块吗?
这可能是一个简单的作用域问题。下面的代码在Python文件(模块)中让我有点困惑:
if __name__ == '__main__':
x = 1
print x
在我工作过的其他编程语言中,这段代码会抛出异常,因为 x
变量只在 if
语句中存在,不应该在外部存在。但是这段代码执行了,并打印了1。有人能解释一下这种行为吗?在模块中创建的所有变量都是全局的/可用于整个模块吗?
Python变量的作用域限制在最内层的函数、类或模块中分配它们的作用域范围内。像if
和while
这样的控制结构不算,因此在if
语句内分配的变量仍然是在函数、类或模块的作用域范围内。
(通过生成器表达式或列表/集合/字典推导定义的隐式函数是算作作用域范围内的,lambda表达式也算。虽然你不能把赋值语句放到它们中间,但是lambda参数和for
循环的目标是隐式赋值的。)
nonlocal
访问这些名称。它们可以在self
上找到(即使它是对象实例而不是类),但这是属性查找的特殊行为,而不是作用域解析。 - Karl Knechtelfor
循环中一样。在3.8及以上版本中,“海象” :=
运算符可以在推导式中使用,以将值分配给外部作用域中的变量:例如,在 x = 0
之后,[_ for x in [1]]
不会修改外部的 x
,但是 [x:=1 for _ in range(1)]
会。 - Karl Knechtel是的,它们在同一个“局部作用域”中,实际上 Python 中常见这样的代码:
if condition:
x = 'something'
else:
x = 'something else'
use(x)
请注意,条件语句中的x
并没有在声明或初始化之前,例如在C或Java中。
换句话说,Python没有块级作用域。但要小心例如:
if False:
x = 3
print(x)
这显然会引发一个NameError
异常。
if False:
的陷阱。 - steoiatslif condition:
i = 2
else:
i = 0
for var in array:
i += 1
-> 这会导致TypeError:不支持的操作数类型'+=':'NoneType'和'int' - chakmearPython中的作用域按照以下顺序搜索:
搜索本地作用域
搜索任何封闭函数的作用域
搜索全局作用域
搜索内建作用域
(来源)
请注意,if
等循环/分支结构未列出 - 只有类、函数和模块在Python中提供作用域,因此在if
块中声明的任何内容都与块外声明的内容具有相同的作用域。变量不会在编译时检查,这就是为什么其他语言会抛出异常的原因。在Python中,只要在需要时变量存在,就不会抛出异常。
与 C 等语言不同,Python 变量在它所在的整个函数(或类、模块)范围内都是可见的,而不仅限于最内层的“块”中。这就好像你在函数(或类、模块)顶部声明了 int x
,只不过在 Python 中你无需声明变量。
请注意,变量 x
的存在只有在运行时才会进行检查 - 也就是当您到达 print x
语句时。如果 __name__
不等于 "__main__"
,那么你将得到一个异常:NameError: name 'x' is not defined
。
正如Eli所说,Python不需要变量声明。在C语言中,你需要这样写:
int x;
if(something)
x = 1;
else
x = 2;
但是在Python中,声明是隐含的,当您分配给x时,它会自动声明。这是因为Python是动态类型语言-在静态类型语言中无法工作,因为根据使用的路径,变量可能在未声明的情况下被使用。在静态类型语言中,这将在编译时被捕获,但是在动态类型语言中允许。
唯一的原因是静态类型语言受限于必须在if
语句之外声明变量,因为有这个问题。拥抱动态语言!
是的。对于for
语句的作用域也是如此。但当然不包括函数。
在你的例子中:如果if
语句中的条件为false,则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
if
语句不成立(即,当你导入模块而不是在顶层执行它时,__name__
不是'__main__'
),那么x
将永远没有被绑定,随后的print x
语句将会抛出一个NameError: name 'x' is not defined
异常。 - Santa