首页 > 解决方案 > 为什么 Python 中的 with 块不需要 global 关键字?

问题描述

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

标签: pythonpython-3.xglobal-variableswith-statement

解决方案


Python 没有块作用域。该with声明没有引入新的范围;语句的主体仍在与该语句相同的范围内with

Python 有 4 种作用域:

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

没有其他构造定义新的范围:not ifstatements,not fororwhile循环,not withstatements,not trystatements,not classstatements。只有定义新函数(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最后,在全局范围内找到一个值。

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


推荐阅读