python 基础---命名空间、作用域、嵌套、闭包
命名空间
从python解释器开始执行之后,就在内存中开辟了一个空间
每当遇到一个变量的时候,就把变量名和值之间的对应关系记录下来。
但是当遇到函数定义的时候解释器只是象征性的将函数名读入内存,表示知道这个函数的存在了,至于函数内部的变量和逻辑解释器根本不关心。
等执行到函数调用的时候,python解释器会再开辟一块内存来存储这个函数里的内容,这个时候,才关注函数里面有哪些变量,而函数中的变量会存储在新开辟出来的内存中。函数中的变量只能在函数的内部使用,并且会随着函数执行完毕,这块内存中的所有内容也会被清空。
“存放名字与值的关系”的空间——命名空间
代码在运行伊始,创建的存储“变量名与值的关系”的空间叫做全局命名空间,在函数的运行中开辟的临时的空间叫做局部命名空间
命名空间一共分为三种:
内置命名空间
———存放了python解释器为我们提供的名字:input,print,str,list,tuple...它们都是我们熟悉的,拿过来就可以用的方法。
———内置的名字在启动解释器的时候被加载进内存里
全局命名空间
———我们写的代码但不是函数中的代码
———是在程序从上到下被执行的过程中依次加载进内存的,放置了我们设置的所有变量名和函数名
局部命名空间
——— 函数
———就是函数内部定义的名字,当调用函数的时候 才会产生这个名称空间,随着函数执行的结束 这个命名空间就又消失
依赖倒转原则
在局部:可以使用全局、内置命名空间中的名字
在全局:可以使用内置命名空间中的
在内置:不能使用局部和全局的名字的
举例:
1 x = 1
2 def f(x):
3 print(x)
4
5 f(10)
6 print(x)
7 # 输出:
8 # 10
9 # 1
作用域
按照生效范围可以分为全局作用域和局部作用域
全局作用域:包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效——globals()
局部作用域:局部名称空间,只能在局部范围内生效,函数——locals()
可以通过globals()和locals()查看全局变量和局部变量
顺序:局部—>闭包函数外的函数—>全局—>内建
1 如果在一个局部(函数)内声明了一个global变量,那么这个变量在局部的所有操作将对全局的变量有效
2 a = 1
3 b = 2
4 def func():
5 x = 'aaa'
6 y = 'bbb'
7 print(locals()) #打印当前局部变量
8 print(globals()) #打印全局变量
9 #
10 func()
11 print(globals())
12 print(locals()) #本地的局部变量
13
14 globals 永远打印全局的名字
15 locals 输出什么 根据locals所在的位置
输出结果:第7行:{'x': 'aaa', 'y': 'bbb'}
第8行:{'b': 2,'a': 1}
第11行:{'b': 2,'a': 1}
第12行:{'b': 2,'a': 1}
作用域举例:global :在局部声明一个全局变量
1 第一部分
2 a = 1
3 def func():
4 a = 2
5 func()
6 print(a)
7 #输出 1
8
9 第二部分
10 a = 1
11 def func():
12 global a
13 a = 2
14
15 func()
16 print(a)
17 #输出 2
对于不可变数据类型 在局部可是查看全局作用域中的变量
但是不能直接修改
如果想要修改,需要在程序的一开始添加global声明
嵌套
函数的嵌套定义
1 def max(a,b):
2 return a if a>b else b
3
4 def the_max(x,y,z): #函数的嵌套调用
5 c = max(x,y)
6 return max(c,z)
7
8 print(the_max(1,2,3))
函数的嵌套定义
nonlocal:在局部声明最近的上一层局部中的变量
1.只能用于局部变量 找上层中离当前函数最近一层的局部变量
2.声明了nonlocal的内部函数的变量修改会影响到离当前函数最近一层的局部变量
3.对全局无效
1 def f1():
2 a = 1
3 def f2():
4 a = 2
5 f2()
6 print('a in f1 : ',a)
7
8 f1()
9 输出结果:1
加上nonlocal
1 def f1():
2 a = 1
3 def f2():
4 nonlocal a
5 a = 2
6 f2()
7 print('a in f1 : ',a)
8
9 f1()
10 输出结果:2
闭包:嵌套函数,内部函数调用外部函数的变量
1 def outer():
2 a = 1
3 def inner():
4 print(a)
5 return inner
6 inn = outer()
7 inn()
outer()是执行函数outer,outer()也就是outer的返回值,即inner,这个是inner的内存地址
则,inn得到的是inner的内存地址,inn()是执行,即执行innner()
函数名就是地址;函数名可以赋值;函数名可以作为容器类型的元素
1 def func():
2 print(123)
3
4 func2 = func #函数名可以赋值,func是地址
5 func2()
6
7 l = [func,func2] #函数名可以作为容器类型的元素
8 print(l)
9 for i in l:
10 i()
函数名可以作为函数的返回值;函数名可以作为函数的参数
1 def func(): 2 print(123) 3 4 def wahaha(f): 5 f() #执行函数,此时执行func() 6 return f #函数名可以作为函数的返回值 7 8 qqxing = wahaha(func) # 函数名可以作为函数的参数,即qqxing = func 9 qqxing()