名称空间与作用域
补充知识
栈区 / 堆区
名称空间
引入:
1. 什么是名称空间?
-名称:定义的名字 空间:存放名字的地方
-名称空间即存放名字与对象映射/绑定关系的地方。
-名称空间只是虚拟的概念。栈区才是真正存在的。
2 。名称空间有包含关系吗?
-名称空间之间本质是没有包含关系的,是互相独立的。
3. 为什么要有名称空间?
-有了名称空间之后,就可以在栈区中存放相同的名字,让所有的名称不冲突。
4. 查找名称空间的优先级是:
-在局部作用域查找名字时,起始位置是局部作用域,所以先查找局部名称空间,如果没有找到,再去全局作用域查找,还没有找到就在内置名称空间中查找,都没有找到就会抛出异常。
5. 查找顺序:局部名称空间>>全局名称空间>>内置名称空间
6. 三种全称空间的个数:内置、全局1 只有一个。局部可以多个。
名称空间的分类(三类)
内建名称空间(也叫内置名称空间)
存放的名字:存放的是python解释器内置的名字
存活周期:python解释器启动则产生,python解释器关闭则销毁。
示例:
>>> len
>>> <built-in function len >
>>> print
>>> <built-in function print >
>>> input
>>> <built-in function input >
全局名称空间
存放的是顶级名字(文件级别的名字)
存活周期:在执行文件执行时生效,文件运行完毕或文件执行期间被删除则失效
x = 1
def foo ():
y = 2
注意,"if" 下面的定义的变量名都是全局的
if 1 > 0
z = 3
if 3 > 0 :
p = 555
局部名称空间
存放函数内定义的名字
存活周期: 在调用函数时临时生效,函数调用完毕失效
示例一:
def f ()
x = 222
f()
示例二:
def func (a, b ):
pass
下面👇调用了4 次func,虽然使用pass 语句,但是在调用函数时,也会产生局部名称空间,且它们每调用一次,都会产生一个新的局部名称空间。
func(10 , 1 )
func(10 , 1 )
func(10 , 1 )
func(10 , 1 )
三种名称空间的之间的关系
1. 三种名称空间的加载顺序:
内置名称空间= > 全局名称空间= > 局部名称空间
2. 三种名称空间中一定要有的名称空间:
内置名称空间、全局名称空间
3. 三种名称空间的销毁顺序:
局部名称空间 =》 全局名称空间 =》 内置名称空间
4. 三种名称空间的名字的查找优先级:在当前所在的位置,一层层向上查找
如果当前在局部名称空间:
局部名称空间 ==> 全局名称空间 ==> 内置名称空间
如果当前在局部名称空间:局部名称空间 => 全局名称空间 => 内置名称空间
input = 100
def func ():
input = 10
print (input )
func()
如果当前在全局名称空间:全局名称空间 --> 内置名称空间
示范一:
input = 111
def func ():
input = 222
func()
print (input )
111
示范二:
x = 222
def func ():
print (x)
x = 111
func()
示范三(难点):名称空间的"嵌套" 关系是以函数定义时为准的,与调用位置无关。
x = 111
def func ():
print (x)
def foo ():
x = 222
func()
foo()
111
示范四(难点):函数的嵌套定义
input = 111
def f1 ():
def f2 ():
print (input )
input = 222
f2()
f1()
示范五(难点):逻辑错误
x = 111
def func ():
print (x)
x = 222
func()
名称空间总结与注意事项
三种名称空间必须要有的是 : 内置名称空间, 全局名称空间
重要概念:名称空间的嵌套关系是在函数定义阶段(检测语法)时确定的,与函数调用的位置无关,与函数定义位置有关。函数的取值位置是个很绕的知识点,最好一步一步分析函数执行步骤,与惯性思维作斗争。
代码一:
x = 111
def func ():
print (x)
x = 222
func()
代码二:
x = 111
def func ():
print (x)
func()
x = 222
示例二
x = 1
def func ():
print (x)
def foo ():
x = 222
func()
foo()
示例三:
input = 111
def f1 ():
def f2 ():
input = 333
print (input )
input = 222
f2()
f1()
示例四
count = 1
def func ():
count = 100
print (count)
func()
示例五:
def f1 ():
m=111
return m
def f2 ():
print (res)
def f3 ():
print (res)
res=f1()
f2()
f3()
示例六:
x=111
def f1 ():
print (x)
x = 222
f1()
示例七:
m = [111 ,]
def func (y ):
m.append(333 )
print (y)
func(m)
m.append(222 )
print (m)
作用域
什么是作用域?
-作用域就是根据名称空间的范围和特点的不同进一步做了归类。
-查看作用域:: globals ( ), locals ( )
-变量的生效范围,分为全局作用域和局部作用域。
全局作用域与局部作用域
全局作用域
-包含:全局名称空间、内置名称空间
-特点:全局存活,全局有效
x就属于全局名称空间,在全局名称空间和局部名称空间都能访问到。
x = 10
def f1 ():
print (x)
print (x)
f1()
globals ()
x = 111
print (globals ())
局部作用域
局部作用域可以引用全局作用域的变量,但不可以改变
x = 10
def f1 ():
x = 20
f1()
print (x)
locals ()
x = 111
def func ():
a = 10
b = 20
print (locals ())
func()
global与nonlocal关键字
global关键字
-使用方式:global x:声明这个x是全局的名字x(x也可以是其他变量)
-针对的是不可变类型的值
-只能在局部名称空间使用。在局部声明一个全局作用域的变量。在 global 语句中列出的名称不得在同一代码块内该 global 语句之前的位置中使用。
-global 用处:如果想在局部修改全局的名字对于的值,且对应得一定要是不可变类的值,这个时候就使用global 。(注意:global 作用就是争对局部中修改全局中不可变类型的值)
代码一:
在全局空间定义一个变量"x" ,函数"foo" ,在函数内部修改"x" 的值
x = 111
def foo ():
x = 222
foo()
print (x)
代码二:
使用"global" 关键字之后
x = 111
def foo ():
global x
x = 222
foo()
print (x)
在 global 语句中列出的名称不得被定义为正式形参,不也得出现于 for 循环的控制目标、class 定义 、函数定义、import 语句或变量标注之中。
局部名称空间不能修改全局名称空间的不可变数据类型的值,只能引用。
c = 1
def func ():
c += 1
print (c)
func()
对于可变类型,也不能使用先取值后修改再赋值给原变量名这种方式,而是使用内置方法来修改。
代码一:
c = [1 ,2 ,3 ]
def func ():
c += [3 ,4 ,5 ]
print (c)
func()
代码二:
c = [1 ,2 ,3 ]
def func ():
c.extend([3 ,4 ,5 ])
print (c)
func()
使用global 关键字,可以在局部修改一个全局变量。
c = 1
def func ():
global c
c += 1
print (c)
func()
nonlocal关键字
-使用方法 : nonlocal x
-作用:修改该函数外层函数包含的变量名对应的值, 也是针对不可变类型(nonlocal 起码在第二次嵌套函数内使用才有意义,能改变一个外层函数的非全局变量)
-注意 : 只能在局部名称空间中查找, 先从外部嵌套的函数找, 没找到再往上找, 如果都没找到则报错,不会去全局修改变量值
代码一:
不做任何处理,此函数应该是打印"f2" 函数下的"x = 333"
x = 111
def f1 ():
x = 222
def f2 ():
x = 333
def f3 ():
x = 444
f3()
print (x)
f2()
f1()
print (x)
代码二:
使用"nonlocal" 关键字,nonlocal 起码在第二次嵌套函数内使用才有意义,能改变一个外层函数的非全局变量
x = 111
def f1 ():
x = 222
def f2 ():
x = 333
def f3 ():
nonlocal x
x = 444
f3()
print (x)
f2()
f1()
代码三:
如果外层函数都没有"x" 这个值,报错
x = 111
def f1 ():
def f2 ():
def f3 ():
nonlocal x
x = 444
f3()
print (x)
f2()
f1()
只能在函数嵌套定义的内层函数中使用,在第一层局部名称空间内使用会报错。用作函数嵌套定义中,在内层函数中声明一个外层局部名称空间的变量。
nonlocal 语句中列出的名称不得与之前存在于局部作用域中的绑定相冲突。
x = 111
def f1 ():
x = 222
def f2 ():
nonlocal x
x = 333
f2()
print (x)
f1()
LEGB原则
-按照LEGB原则就近取值,取值顺序单向不可逆。
-LEGB代表名字查找顺序 :Local本地 --> Enclosed嵌套函数的外层函数内部 --> Global全局 -->Builtin内置
L ——Local(function); 函数内的名字空间
E —— Enclosing function locals ;外部嵌套函数的名字空间(例如closure)
G—— Global(module); 函数定义所在模块(文件)的名字空间
B —— Builtin(Python); Python内置模块的名字空间
(从局部开始找时)局部名称空间 --> 全局名称空间 --> 内置名称空间
name = 'xiao'
def index ():
name = 'quan'
age = 18
print (name)
print (f"这是局部的变量 :>>>> {locals ()} " )
index()
print (f"这是外部的变量 :>>>> {globals ()} " )
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏