一、命名空间
1、定义
名称到对象的映射。命名空间是一个字典的实现,键为变量名,值是变量对应的值。各个命名空间是独立没有关系的,一个命名空间中不能有重名,但是不同的命名空间可以重名而没有任何影响。
2、命名空间的分类
1)、全局命名空间( Global):每个模块加载执行时创建的,记录了模块中定义的变量,包括模块中定义的函数、类、其他导入的模块、模块级的变量与常量。
2)、局部命名空间(Local):每个函数所拥有的命名空间,记录了函数中定义的所有变量,包括函数的入参、内部定义的局部变量。
3)、python内置命名空间(Built-in):任何模块均可以访问,放着内置的函数和异常(比如:input,print,str,list,tuple...)。
3、生命周期
3.1、加载顺序
内置命名空间(程序运行前加载)-->全局命名空间(程序运行中:从上到下加载)-->局部命名空间(程序运行中:调用时才加载)
3.2、取值顺序
在局部调用:局部命名空间-->全局命名空间-->内置命名空间
在全局调用:全局命名空间-->内置命名空间
综上所述,在寻找变量时,从小范围,一层一层到大范围去找寻。
4、作用域
4.1、定义
作用域是针对变量而言,指申明的变量在程序里的可应用范围。或者称为变量的可见性。
4.2、分类
按照生效范围可以分为全局作用域和局部作用域。
1)、全局作用域:包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效
2)、局部作用域:局部名称空间,只能在局部范围内生效
4.3、两个常用的内置函数
locals() 和globals(),它们提供了基于字典的访问局部和全局变量的方式。
1)、locals():函数会以字典类型返回当前位置的全部局部变量。
2)、globals():函数会以字典类型返回当前位置的全部全局变量。
#在全局作用域内 print(globals()) print(locals()) #输出结果: {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__':
<_frozen_importlib_external.SourceFileLoader object at 0x0000018DA3453FD0>, '__spec__': None, '__annotations__': {},
'__builtins__': <module 'builtins' (built-in)>, '__file__': 'd:/python10/day10/homework.py', '__cached__': None} {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__':
<_frozen_importlib_external.SourceFileLoader object at 0x0000018DA3453FD0>, '__spec__': None, '__annotations__': {},
'__builtins__': <module 'builtins' (built-in)>, '__file__': 'd:/python10/day10/homework.py', '__cached__': None}
#在函数局部作用域内 name = 'wusir' def func(): name = 'alex' print(globals()) print(locals()) #{'name': 'alex'} func() #输出结果: {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__':
<_frozen_importlib_external.SourceFileLoader object at 0x000002397E843FD0>, '__spec__': None, '__annotations__': {},
'__builtins__': <module 'builtins' (built-in)>, '__file__': 'd:/python10/day10/homework.py', '__cached__': None, 'name': 'wusir',
'func': <function func at 0x000002397CA62E18>} {'name': 'alex'}
5、关键字(global 与 nonlocal)
5.1、global的作用
1)、声明一个全局变量
2)、在局部作用域想要对全局作用域的全局变量进行修改时,需要用到 global(限于字符串,数字)
def func(): global a a = 2 print(a) #2 func() print(a) #2 #输出结果 2 2
注意:对可变数据类型(list,dict,set)可以直接引用不用通过global(以下是实例)
li = [1,2,3] dic = {'a':'b'} def change(): li.append('a') dic['q'] = 'g' print(dic) #{'a': 'b', 'q': 'g'} print(li) #[1, 2, 3, 'a'] change() print(li) #[1, 2, 3, 'a'] print(dic) #{'a': 'b', 'q': 'g'} #输出结果 {'a': 'b', 'q': 'g'} [1, 2, 3, 'a'] [1, 2, 3, 'a'] {'a': 'b', 'q': 'g'}
5.2、nonlocal的作用
1)、不能修改全局变量
2)、在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,并且引用的哪层,从那层及以下此变量全部发生改变
def add_b(): b = 42 def do_global(): b = 10 print(b) #10 def dd_nonlocal(): nonlocal b b = b + 20 print(b) #30 dd_nonlocal() print(b) #30 do_global() print(b) #42 add_b() #输出结果 10 30 30 42
二、函数的嵌套
def fun1(): print(111) def fun2(): print(222) fun1() fun2() #输出结果 222 111
函数的作用域链:小范围作用域可以使用大范围的变量,但是反之不行,它是单向的。
print(111) #执行顺序--1 def fun2(): print(222) #执行顺序--3 def fun3(): print(666) #执行顺序--5 print(444) #执行顺序--4 fun3() print(888) #执行顺序--6 print(333) #执行顺序--2 fun2() print(555) #执行顺序--7 #输出结果 111 333 222 444 666 888 555