为什么 Python 中的 with block 不需要全局关键字?



我正在使用with块从文件中提取信息,我很惊讶with块中声明的任何变量都是全局的。它们不应该是with块的局部,在更改全局变量之前不应该使用global myVar吗?毕竟,with定义了一个代码块,对吧?

Python 没有块作用域。with声明没有引入新的范围;语句的正文仍位于具有with语句的同一范围内。

Python 有 4 种作用域:

  1. 内置作用域,定义任何模块中可用的名称,无需显式import
  2. 全局作用域,每个模块一个。
  3. 非本地作用域
  4. 本地作用域:由函数定义。

没有其他构造定义新作用域:不是if语句,不是forwhile循环,不是with语句,不是try语句,不是class语句。只有定义新函数(def语句、lambda 表达式和推导(的东西才会创建新的(局部(作用域。

每个名称首先在本地作用域中查找(如果不在函数定义中,则可能是全局作用域(,然后在任何非局部作用域中查找(如果函数是在全局作用域中定义的,则可能不存在,而不是在另一个本地作用域中(,然后是全局作用域,最后是在内置作用域中。

非本地作用域

只是不是当前本地作用域的作用域。对于在全局作用域定义的模块,最接近的封闭非本地作用域全局作用域。

但是,如果一个函数是在另一个函数中定义的,则最接近的封闭非局部作用域是定义该函数的局部作用域。

函数可以嵌套得相当深,因此在当前本地作用域和可以进行名称查找的全局作用域之间可能有 0 个或更多其他本地作用域。例如

x1 = 'a'
def f1():
x2 = 'b'
def f2():
x3 = 'c'
def f3():
x4 = 'd'
print(x1 + x2 + x3 + x4)
f3()
f2()
f1()

这种混乱的输出将是abcd.当print语句的参数需要四个变量中每个变量的值时,每个查找都会从局部范围开始。那里只找到x4的值;其他查找扩展到最近的封闭非本地范围,即f2的范围。在那里找到x3的值,因此对x1x2的查找扩展到下一个非本地范围,即f1。 找到x2,因此f1延长另一个停靠点。最后,在全局范围内找到x1的值。

因此,非本地作用域与其说是一种特殊的作用域,不如说是当前执行函数的非本地作用域的名称。它将是封闭函数的本地作用域或全局作用域。

with语句不会创建作用域(就像if, for and while也不会创建作用域一样(。

结果,Python 将分析代码并查看您在 with 语句中进行了赋值,从而进行变量赋值。

with作用域之前进行初始化可能更安全,因为在 with 语句之后,我们可以安全地假设变量存在。另一方面,如果变量应该在 with 语句中赋值,那么在 with 语句之前不初始化它实际上会导致额外的检查:如果在 with 语句中以某种方式跳过赋值,Python 将出错。

相关内容

  • 没有找到相关文章

最新更新