Python命名空间与作用域测试代码运行结果原理咨询
首先明确三个变量作用域声明的核心规则:
- 无任何声明的变量赋值:默认在当前函数的本地作用域创建或修改变量,不会影响外层作用域的同名变量
nonlocal声明:指定当前变量绑定到**外层嵌套函数(非全局层)**作用域中已存在的同名变量,赋值操作会直接修改外层嵌套函数里的对应变量global声明:指定当前变量绑定到最顶层全局作用域的同名变量,会跳过所有中间嵌套函数层,和嵌套层内的同名变量完全独立、互不影响
以下是缩进修正后的可运行示例代码:
def scope_test(): def do_local(): spam = "local spam" def do_nonlocal(): nonlocal spam spam = "nonlocal spam" def do_global(): global spam spam = "global spam" spam = "test spam" do_local() print("After local assignment:", spam) do_nonlocal() print("After nonlocal assignment:", spam) do_global() print("After global assignment:", spam) scope_test() print("In global scope:", spam)
逐行对应输出逻辑,重点解释疑惑的后两行结果:
第一行输出
After local assignment: test spamdo_local()内的spam = "local spam"是函数自身的本地变量,和外层scope_test里的spam完全无关,因此外层spam保留初始值test spam。第二行输出
After nonlocal assignment: nonlocal spamdo_nonlocal()用nonlocal声明spam绑定到外层scope_test作用域的spam,赋值操作直接修改了scope_test内的spam值为nonlocal spam,打印时直接读取该值。第三行(倒数第二行)输出
After global assignment: nonlocal spamdo_global()内的global spam声明,代表这个函数里操作的spam是全局作用域的变量,和scope_test内部的spam是完全独立的两个变量。执行spam = "global spam"时,只会修改全局作用域的spam,根本碰不到scope_test内部存的nonlocal spam。
这行打印是在scope_test函数内部执行,读取的是scope_test自身作用域的spam,因此值还是之前修改的nonlocal spam。最后一行输出
In global scope: global spamscope_test执行完毕回到全局作用域,此时读取的是全局作用域下的spam,也就是do_global()里赋值的global spam,因此输出该值。
关键误区提醒:
global不会把当前嵌套层的变量修改为全局变量,它是直接开辟/指向全局作用域的独立同名变量,和嵌套层内的变量互不干扰。
内容的提问来源于stack exchange,提问作者Gilad Tayeb

