💟一、函数的命名空间和作用域
👾1、函数的命名空间
✨什么是命名空间?
假如有一串代码,观察其输出结果:
def f(): a = 1 return a print(a) 输出结果: Traceback (most recent call last): File "E:/python代码/11/文件一.py", line 4, in <module> print(a) NameError: name 'a' is not defined
报错了!错误是“name 'a' is not defined”。变量a没有被定义。。。为啥?我明明定义了a=1呀!
那我们就要了解一下Python代码运行时遇到函数时怎么做的:
首先从python解释器开始执行之后,就在内存中开辟了一个空间每当遇到一个变量的时候,就把变量名和值之间的对应关系记录下来。但是当遇到函数定义的时候解释器只是象征性的将函数名读入内存,表示知道这个函数的存在了,至于函数内部的变量和逻辑解释器根本不关心。等执行到函数调用的时候,python解释器会再开辟一块内存来存储这个函数里的内容,这个时候,才关注函数里面有哪些变量,而函数中的变量会存储在新开辟出来的内存中。函数中的变量只能在函数的内部使用,并且会随着函数执行完毕,这块内存中的所有内容也会被清空。
我们给这个“存放名字与值的关系”的空间起了一个名字——叫做命名空间
代码在最开始创建的存储“变量名与值的关系”的空间叫做全局命名空间,在函数内部运行中开辟的临时的空间叫做局部命名空间
✨函数命名空间三大类
函数命名空间一共分为三大类
1、内置命名空间 —— python解释器 # 就是python解释器一启动就可以使用的名字存储在内置命名空间中 # 内置的名字在启动解释器的时候被加载进内存里 2、全局命名空间 —— 我们写的代码但不是函数中的代码 # 是在程序从上到下被执行的过程中依次加载进内存的 # 放置了我们设置的所有变量名和函数名 3、局部命名空间 —— 函数 # 就是函数内部定义的名字 # 当调用函数的时候 才会产生这个名称空间 随着函数执行的结束 这个命名空间就又消失了 #在局部:可以使用全局、内置命名空间中的名字 #在全局:可以使用内置命名空间中的名字,但是不能用局部中使用 #在内置:不能使用局部和全局的名字的
内置命名空间:内置命名空间中存放了Python解释器为我们提供的名字(函数)我们不需要定义,都是我们熟悉的打开解释器就能够直接使用如:input、print、str、set……
✨三种命名空间之间的加载与取值顺序
加载顺序:内置命名空间(程序运行前加载 > 全局命名空间(程序运行中:从上到下加载) > 局部命名空间(程序运行中:调用时才加载)
在局部调用时:局部命名空间 > 全局命名空间 > 内置命名空间
在全局调用时:全局命名空间 > 内置命名空间
例子:
a = 10 def f(): a = 1 print(a) f() print(a) 输出结果: 1 10
👾2、函数的作用域
作用域就是作用范围,按照生效范围可以分为全局作用域和局部作用域。全局作用域:包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效
局部作用域:局部名称空间,只能在局部范围内生效
✨globals和locals方法
locals():
函数会以字典类型返回当前位置的全部局部变量。\globals():
函数会以字典类型返回当前位置的全部全局变量。def func(): a = 1 print(locals()) print(globals()) print('========================分割线==========================') func() print(locals()) print(globals())
输出结果:
编辑
✨global关键字
1、global是Python中的全局变量关键字。\
2、变量分为局部变量与全局变量,局部变量又可称之为内部变量。\
3、由某对象或某个函数所创建的变量通常都是局部变量,只能被内部引用,而无法被其它对象或函数引用。\
4、全局变量既可以是某对象函数创建,也可以是在本程序任何地方创建。全局变量是可以被本程序所有对象或函数引用。\
5、global关键字的作用是可以使得一个局部变量为全局变量例子:
在my函数中,在 x 前面加 global,my函数将 x 赋为8,此时全局变量中的 x 值改变。需要注意的是 global 需要在函数内部声明,若在函数外声明,则函数依然无法操作 x 。
x = 4 def my(): global x x = 8 print("x = ", x) print("x = ", x) my() print("x = ", x) 输出结果是: x = 4 x = 8 x = 8
💟二、函数的嵌套和作用域链
👾函数的嵌套调用
def max2(x,y):
m = x if x>y else y
return m
def max4(a,b,c,d):
res1 = max2(a,b)
res2 = max2(res1,c)
res3 = max2(res2,d)
return res3
ret = max4(1,2,4,3)
print(ret)
输出结果:
4
👾函数的嵌套定义
def f1():
print("in f1")
def f2():
print("in f2")
f2()
f1()
输出结果:
in f1
in f2
def f1():
def f2():
def f3():
print("in f3")
print("in f2")
f3()
print("in f1")
f2()
f1()
输出结果:
in f1
in f2
in f3
👾函数的作用域链
a = 1
def outer():
a = 5
def inner():
a = 2
def inner2():
nonlocal a
a += 1
print('inner2',a)
inner2()
print('##a##:',a)
inner()
print('**a**:',a)
outer()
print('全局:',a)
输出结果:
inner2 3
##a##: 3
**a**: 5
全局: 1
👾nonlocal关键字
#nonlocal 只能用于局部变量,找上层中离当前函数最近一层的局部变量且外部必须有这个变量 #声明了nonlocal的内部函数的变量修改会影响到离当前函数最近一层的局部变量 #对全局无效,在内部函数声明nonlocal变量之前不能再出现同名变量 #对局部也只是对最近一层有影响
def f1(): a = 1 def f2(): nonlocal a a = 2 f2() print('a in f1 : ',a) f1() 输出结果: a in f1 : 2
👾global关键字
# 对于不可变数据类型 在局部可是查看全局作用域中的变量 # 但是不能直接修改 # 如果想要修改,需要在程序的一开始添加global声明 # 如果在一个局部(函数)内声明了一个global变量,那么这个变量在局部的所有操作将对全局的变量有效