Python中的global和nonlocal
在Python中,一个变量的scope范围从小到大分成4部分:Local Scope(也可以看成是当前函数形成的scope),Enclosing Scope(简单来说,就是外层函数形成的scope),Global Scope(就是当前文件形成的scope),Builtins Scope(简单来说,就是Python内置的变量位于最顶层的scope)。当Python开始查找一个非限定的变量名时(像obj.attr中的attr,就是一个被限定的变量名字,它被限定在obj对象中,而普通的变量名就是没有限定的),总是从当前变量名所处的scope开始,顺着前面提到的scope链开始往上查找,一旦查找到就不会往上再继续查找,如果查找完整个scope链还是没找到,Python会报错。
上面提到的变量名查找顺序,可以简单的记为LEGB(每一个scope的首字母),而global和nonlocal,可以改变查找顺序。
global
在文件中声明的变量自动成为global的,而如果想在一个函数里面声明一个全局变量,就需要使用global关键字:
global var1, var2, ... # 多个变量用逗号隔开
对于global关键字,需要注意以下几点:
1 当Python看到一个变量由global变量声明,开始查找的scope不是从这个变量当前所在的scope开始查找,而是从Global Scope开始查找;如果Global Scope没有找到,就会继续到Builtins Scope查找;
2 global关键字声明的对象允许赋值,如果这个变量之前不存在,那么,这次赋值就是创建了一个全局变量;如果这个变量之前存在,那么,这次赋值就改变了这个全局变量的值:
def test(): global x x = 1 # x之前不存在,因此在Global Scope创建了一个全局变量x x = 1 def test(): global x x = 99 # x之前在Global Scope中已经存在,因此这里是改变x的值
3 只要被global关键字声明的变量,都会成为全局变量,如果该变量原来不是全局变量,也会如此,并且,如果之前Global Scope里面有同名变量,那么被global声明的变量会取代这个同名变量:
x = 99 def test(): x = 88 global x # 这样做的话Python会产生警告:SyntaxWarning: name 'x' is assigned to before global declaration >>>print(x) # 一开始访问的是全局变量x >>>99 >>>test() # 执行test函数之前,原本函数里面的局部变量x成为了全局变量,并取代原来的全局变量 >>>print(x) # 现在访问的是取代后的全局变量x,值变为88 >>>88 # 在看一个例子,加入开始没有定义全局变量x def test(): x = 88 global x # 仍会产生相同的警告 >>>test() >>>print(x) # 打印结果为88!!! >>>88
nonlocal
nonlocal是Python 3.X加入进来的关键字,Python 2.X中没有。在Python中,嵌套函数是可以访问外部函数的变量的(至少在>Python 2.2的版本是这样的,在Python 2.2之前的版本中,变量的查找从当前函数开始,然后直接到Global Scope,Builtins Scope,跳过了外层函数),但是却不可以改变外部函数变量的值,如果确实要改变,就的使用nonlocal变量进行声明:
nonlocal var1, var2,... # 只在Python 3.X中支持,多个变量用逗号隔开
对于nonlocal关键字,需要注意以下几点:
1 nonlocal关键字只在Python 3.X中支持,Python 2.X没有这个关键字;
2 nonlocal关键字只可以在函数内部使用,在其他地方使用会报错;
3 nonlocal声明的变量,之前必须已经存在(并且是在外部函数中存在),如果变量不存在就对这个变量赋值,会报错,这点和global关键字不一样:
# 变量存在于Global Scope x = 99 def test(): nonlocal x # 报错:SyntaxError: name 'x' is assigned to before nonlocal declaration # 变量存在于当前函数 def test(): x = 99 nonlocal x # 报错:SyntaxError: name 'x' is assigned to before nonlocal declaration
4 对于nonlocal声明的变量,只会在外部函数中查找该变量,不会在Global Scope和Builtins Scope中查找
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2013-06-23 从汇编看c++中指向成员变量的指针(一)