三、名称空间(命名空间)
(一)什么是名称空间
Python解释器开始执行之后,就会在内存中开辟了一个空间,每当遇到一个变量的时候,就会把变量名(内存地址)和值之间的关系记录下来,但是当遇到函数定义的时候,解释器只是把函数名(函数的内存地址)读入内存,表示这个函数存在了,而函数内部的变量和逻辑,解释器是不关心的,也就是说一开始的时候函数只是加载进来了,仅此而已,只有当函数被调用和访问的时候,解释器才会根据函数内部声明的变量开进行开辟变量的内部空间,随着函数执行完毕,这些函数内部变量占用的空间也会随着函数执行完毕被清空,我们给存放名字和值的关系的空间起一个名字叫:名称空间(命名空间),我们的变量在存储的时候就是存储在这片空间中的。(出自邱彦涛老师,我的偶像)
(二)名称空间的分类
在python中名称空间分为三部分:
内置空间
全局空间
局部空间内置空间:存放python解释器为我们提供的名字,len、print、global等等
全局空间:用来存放py文件顶格运行时声明的变量
局部空间:用来存放在函数运行时声明的变量
名称空间加载顺序:
内置名称空间 > 全局名称空间 > 局部名称空间
变量取值顺序:
局部名称空间 > 全局名称空间 > 内置名称空间
(三)作用域
作用域就是作用范围,作用域分为两类:
全局作用域
局部作用域全局作用域:整个文件的任何位置都可以使用
包含:内置名称空间 + 全局名称空间
globals()函数可以查看全局作用域中的变量和函数信息a = 10
b = 20
def func(args1, args2):
print(args1)
print(args2)
print(globals())
return None
func(30, 40)
运行结果:
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001B61F2786D8>, '__spec__': None, '__annotations__': {}, '__builtins__': , '__file__': 'D:/python_S26/day10/exercise.py', '__cached__': None, 'a': 10, 'b': 20, 'func': }
局部作用域:在函数内部可以使用
包含:局部名称空间
locals()函数可以查看当前作用域中的变量和函数信息(建议查看局部)a = 10
b = 20
def func(args1, args2):
print(args1)
print(args2)
print(locals())
return None
func(30, 40)
运行结果:
30
40
{'args2': 40, 'args1': 30}
四、函数名的使用
(一)作为值
函数名可以当作值,赋值给另一个变量
def func():
print("zxd")
name = func # 函数名赋值给另一个变量
print(func)
print(name)
name()
运行结果:
zxd
(二)作为参数
函数名可以当作另一个函数的参数来使用
def func():
print("zxd")
def name(args):
print(args) #
args()
name(func)
运行结果:
zxd
(三)作为返回值
函数名可以当作另一个函数的返回值来使用
def name():
print("zxd")
def func():
return name
func()()
运行结果:
zxd
(四)作为容器中的元素
函数名可以当作元素存储在容器中
def login():
print("登录")
def register():
print("注册")
def look():
print("浏览商品")
def buy():
print("购买商品")
msg = """
1.注册
2.登录
3.浏览商品
4.购买商品
请选择序号:"""
dic_func = {
"1": register,
"2": login,
"3": look,
"4": buy,
}
while True:
num = input(msg)
if num in dic_func.keys():
dic_func[num]()
else:
print("输入错误!")
五、函数嵌套
(一)交叉嵌套
函数参数作为另一个函数的参数,从而插入另一个函数中
看一个例子:
def func1(a):
print(1)
a()
print(2)
def func2():
print(3)
re = func3()
print(re)
print(4)
def func3():
print(5)
func1(func2)
运行结果:
1 3 5 None 4 2
运行顺序
(二)内部嵌套
函数内部嵌套函数
看一个例子
def func1():
print(1)
def func2():
print(2)
def func3():
print(3)
func3()
print(4)
func2()
print(5)
func1()
运行结果:
1 2 3 4 5
运行顺序
六、global和nonlocal
(一)global
全局中的变量在函数内部只有使用权,可以拿来用,但是不能更改
num = 10
def func():
num = num + 1
print(num)
func()
print(num)
# UnboundLocalError: local variable 'num' referenced before assignment
如果想在局部中修改全局变量,必须先用global声明要修改的全局变量
num = 10
def func():
global num
num = num + 1
print(num) # 11
func()
print(num) # 11
在函数中使用了global声明了变量,但全局空间中并没有这个变量时,global会在全局空间中开辟这个变量
def func():
global num
num = 10
print(num) # 10
func()
print(num) # 10
总结:
可以在局部空间修改全局空间的是变量
若全局空间无声明的变量则创建该变量
global有效的控制因误操作在局部空间修改全局空间的变量
(二)nonlocal
nonlocal修改离nonlocal最近的上一层名称空间的变量,但只修改局部空间中的变量
num = 10
def func1():
num = 20
def func2():
num = 30
def func3():
nonlocal num
num += 1
print(num)
func3()
print(num)
func2()
print(num)
func1()
print(num)
运行结果:
31 31 20 10
nonlocal声明的变量如果是全局空间中的变量就会报错,并且nonlocal不会创建变量
num = 10
def func1():
def func2():
def func3():
nonlocal num # 局部空间内没有变量num
print(num)
func3()
print(num)
func2()
print(num)
func1()
print(num)
运行结果:
SyntaxError: no binding for nonlocal 'num' found
当前空间如果有变量,在去用nonlocal声明该变量,会报错,nonlocal只能声明上一层名称空间的变量
num = 10
def func1():
def func2():
def func3():
num = 10
nonlocal num #
print(num)
func3()
print(num)
func2()
print(num)
func1()
print(num)
运行结果:
SyntaxError: name 'num' is assigned to before nonlocal declaration