python进阶之命名空间与作用域
1|0命名空间 Namespace
Namespace命名空间,命名空间是一个字典(dictionary),它的键就是变量名,它的值就是那些变量的值。命名空间的一大作用是避免名字冲突。
python使用命名空间记录变量的轨迹。python中有三个命名空间:
命名空间 |
名称 |
记录数据 |
函数的命名空间 |
局部命名空间 (local namespace) |
记录了函数的参数和局部定义的变量 |
模块的命名空间 |
全局命名空间 (global namespace) |
记录了模块的变量,包括函数,类,其他导入的模块,模块级的变量和常量 |
内置命名空间 |
内置命名空间 (build-in) |
存放内置的函数和异常,例如:abs() |
内置函数 locals(),返回当前函数的局部命名空间
1 2 3 4 5 6 7 8 9 10 11 12 | <code - pre class = "code-pre" id = "pre-skDNyT" ><code - line class = "line-numbers-rows" >< / code - line>x = 100 <code - line class = "line-numbers-rows" >< / code - line> <code - line class = "line-numbers-rows" >< / code - line> def fun(): <code - line class = "line-numbers-rows" >< / code - line> a = 1 <code - line class = "line-numbers-rows" >< / code - line> b = 2 <code - line class = "line-numbers-rows" >< / code - line> print locals () <code - line class = "line-numbers-rows" >< / code - line> return a + b <code - line class = "line-numbers-rows" >< / code - line> <code - line class = "line-numbers-rows" >< / code - line>fun() <code - line class = "line-numbers-rows" >< / code - line>结果: <code - line class = "line-numbers-rows" >< / code - line>{ 'a' : 1 , 'b' : 2 } < / code - pre> |
内置函数globals(),返回当前模块的全局命名空间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <code - pre class = "code-pre" id = "pre-687fbQ" ><code - line class = "line-numbers-rows" >< / code - line>x = 100 <code - line class = "line-numbers-rows" >< / code - line> <code - line class = "line-numbers-rows" >< / code - line> def fun(): <code - line class = "line-numbers-rows" >< / code - line> a = 1 <code - line class = "line-numbers-rows" >< / code - line> b = 2 <code - line class = "line-numbers-rows" >< / code - line> print locals () <code - line class = "line-numbers-rows" >< / code - line> return a + b <code - line class = "line-numbers-rows" >< / code - line> <code - line class = "line-numbers-rows" >< / code - line> <code - line class = "line-numbers-rows" >< / code - line>fun() <code - line class = "line-numbers-rows" >< / code - line> print globals () <code - line class = "line-numbers-rows" >< / code - line>结果: <code - line class = "line-numbers-rows" >< / code - line>{ 'a' : 1 , 'b' : 2 }{ '__builtins__' : <module '__builtin__' (built - in )>, '__file__' : 'locals.py' , '__package__' : None , 'x' : 100 , 'fun' : <function fun at 0x7fb18df93668 >, '__name__' : '__main__' , '__doc__' : None } < / code - pre> |
1|1命名空间查找顺序
当代码要使用变量x的值时,Python解释器回到所有可用的命名空间去查找变量,顺序:
- 局部命名空间:当前函数或者类的方法。如果函数定义了一个局部变量x,解释器使用它,停止搜索。
- 在父函数或嵌套的命名空间中搜索
- 全局命名空间,搜索当前的模块,如果模块定义了名为x的变量,函数,或者类,解释器使用它。
- 内置命名空间:对每个模块都是全局的,作为最后的尝试,python将假设x为内置函数或变量。
- 如果 Python 在这些名字空间找不到 x,它将放弃查找并引发一个 NameError 异常,如,NameError: name 'aa' is not defined。
1|2命名空间的生命周期
- 内置命名空间,python解释器启动时创建,退出时销毁
- 全局命名空间,模块定义被解释器读入时创建,解释器退出时销毁
- 局部命名空间,函数调用时创建,函数返回或者异常时销毁
1 2 3 4 5 6 7 8 9 10 11 | <code - pre class = "code-pre" id = "pre-rQ68B4" ><code - line class = "line-numbers-rows" >< / code - line> def fun(): <code - line class = "line-numbers-rows" >< / code - line> a = 1 <code - line class = "line-numbers-rows" >< / code - line> <code - line class = "line-numbers-rows" >< / code - line>fun() <code - line class = "line-numbers-rows" >< / code - line> print a <code - line class = "line-numbers-rows" >< / code - line> <code - line class = "line-numbers-rows" >< / code - line>Traceback (most recent call last): <code - line class = "line-numbers-rows" >< / code - line> File "find_namespce.py" , line 6 , in <module> <code - line class = "line-numbers-rows" >< / code - line> print a <code - line class = "line-numbers-rows" >< / code - line>NameError: name 'a' is not defined < / code - pre> |
2|0作用域
作用域针对变量而言,指申明了变量在程序里的可应用范围。只有函数,类,模块会产生作用域,代码块不会产生作用域。例如for循环,if判断都不产生作用域。
作用域可以划分成4类:
- 局部作用域
- 嵌套作用域
- 全局作用域
- 内建作用域
2|1作用域链
python中作用域链,变量会由内到外去找,先去自己的作用域找,自己没有在去上级去找,一直到找不到报错。
特性:
函数未执行之前,作用域已经形成,作用域链也生成了
1 2 3 4 5 6 7 8 9 10 | <code - pre class = "code-pre" id = "pre-hcBxdy" ><code - line class = "line-numbers-rows" >< / code - line>name = "lzl" <code - line class = "line-numbers-rows" >< / code - line> <code - line class = "line-numbers-rows" >< / code - line> def f1(): <code - line class = "line-numbers-rows" >< / code - line> print (name) <code - line class = "line-numbers-rows" >< / code - line> <code - line class = "line-numbers-rows" >< / code - line> def f2(): <code - line class = "line-numbers-rows" >< / code - line> name = "eric" <code - line class = "line-numbers-rows" >< / code - line> f1() <code - line class = "line-numbers-rows" >< / code - line>f2() < / code - pre> |
这里有解释
#在f2中执行f1时,f1的作用域链已经形成,向上级找,name为lzl。
2|2全局变量和局部变量
全局变量:所有函数之外定义的变量
局部变量:函数内部定义的变量 或者类,模块里的变量
全局变量和局部变量使用:
函数内部的变量名如果第一次出现,且出现在=前面,即被视为定义了一个局部变量,不管全局域中有没有该变量名,函数中使用的将是局部变量。
(即声明了一个新的局部变量。如果这个变量名字和全部变量名字相同,那么局部变量名字会覆盖全局变量名字。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <code - pre class = "code-pre" id = "pre-CxxAKr" ><code - line class = "line-numbers-rows" >< / code - line>b = 2 <code - line class = "line-numbers-rows" >< / code - line> <code - line class = "line-numbers-rows" >< / code - line> def fun(): <code - line class = "line-numbers-rows" >< / code - line> <code - line class = "line-numbers-rows" >< / code - line> a = 1 <code - line class = "line-numbers-rows" >< / code - line> b = 10 <code - line class = "line-numbers-rows" >< / code - line> print locals () <code - line class = "line-numbers-rows" >< / code - line> print a <code - line class = "line-numbers-rows" >< / code - line> print b <code - line class = "line-numbers-rows" >< / code - line> <code - line class = "line-numbers-rows" >< / code - line> <code - line class = "line-numbers-rows" >< / code - line> <code - line class = "line-numbers-rows" >< / code - line>fun() <code - line class = "line-numbers-rows" >< / code - line> print globals () <code - line class = "line-numbers-rows" >< / code - line>{ 'a' : 1 , 'b' : 10 } <code - line class = "line-numbers-rows" >< / code - line> 1 <code - line class = "line-numbers-rows" >< / code - line> 10 <code - line class = "line-numbers-rows" >< / code - line>{ 'b' : 2 , '__builtins__' : <module '__builtin__' (built - in )>, '__file__' : 'find_namespce.py' , '__package__' : None , 'fun' : <function fun at 0x7fb7bda1d668 >, '__name__' : '__main__' , '__doc__' : None } < / code - pre> |
局部变量如何使用全局变量:
[关键字 global]
1 2 3 4 5 6 7 8 9 10 11 | <code - pre class = "code-pre" id = "pre-EMtbrN" ><code - line class = "line-numbers-rows" >< / code - line> #[demo1] <code - line class = "line-numbers-rows" >< / code - line> <code - line class = "line-numbers-rows" >< / code - line>Num = 100 <code - line class = "line-numbers-rows" >< / code - line> def func(): <code - line class = "line-numbers-rows" >< / code - line> global Num #声明这个Num是全局。如果全局变量已经有这个Num变量那就是指的它 如果全局没这个Num那就新定义一个全局变量。 <code - line class = "line-numbers-rows" >< / code - line> Num = 200 #凡是在函数内部Num始终是指全局变量。这里不可能有个局部变量叫Num的。 <code - line class = "line-numbers-rows" >< / code - line> print (Num ) <code - line class = "line-numbers-rows" >< / code - line> <code - line class = "line-numbers-rows" >< / code - line>func() <code - line class = "line-numbers-rows" >< / code - line> print (Num ) #输出200 说明修改的就是全局变量啊 < / code - pre> |
1 2 3 4 5 6 7 8 9 | <code - pre class = "code-pre" id = "pre-PGi6pC" ><code - line class = "line-numbers-rows" >< / code - line> #[demo2] <code - line class = "line-numbers-rows" >< / code - line> <code - line class = "line-numbers-rows" >< / code - line> def func(): <code - line class = "line-numbers-rows" >< / code - line> global Num #声明这个Num是全局的哦。而且恰恰是此时没有一个全局变量是Num。那么如果全局没这个Num那就新定义一个Num的全局变量。 <code - line class = "line-numbers-rows" >< / code - line> Num = 200 <code - line class = "line-numbers-rows" >< / code - line> print (Num ) <code - line class = "line-numbers-rows" >< / code - line> <code - line class = "line-numbers-rows" >< / code - line>func() <code - line class = "line-numbers-rows" >< / code - line> print (Num ) #输出200 说明新定义了一个全局变量Num</code-pre> |
如果不是明显要局部变量和全局变量互相操作能不纠缠就不纠缠。也就是定义变量名字的时候 要严格规范。按照开发规范来定义名字。全局大写或者加上“_”开头,这是避免不必要问题的根本消灭问题。如果实在是场景需求 局部要操作修改赋值全局变量。那就使用global。
__EOF__

本文链接:https://www.cnblogs.com/goldsunshine/p/10948475.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理