一、命名空间和变量的作用域
1、命名空间
命名空间一共分为三种:
全局命名空间:我理解为写代码的文件里,且除开函数的地方;
局部命名空间:就函数内部;
内置命名空间:Python解释器的地盘,我将其理解为整个工程文件的范围。
内置命名空间中存放了python解释器为我们提供的函数和变量名:input,print,str,list,tuple...可以直接使用。
三种命名空间之间的加载与取值顺序:内置命名空间(程序运行前加载)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程序运行中:调用时才加载)
取值:在局部调用:局部命名空间->全局命名空间->内置命名空间。
2、作用域
作用域就是作用范围,按照生效范围可以分为全局作用域和局部作用域。
全局作用域:包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效。
局部作用域:局部名称空间,只能在局部范围内生效。
2.1 global方法
得到所有的全局变量和方法。
2.2 locals方法
得到调用处所有的局部变量和方法。
2.3 global
在局部命名空间声明一个全局变量。这个时候,可以在局部改变全局变量的值。
a = 10print(locals())def func(): global a a = 20 b = 20 def func(): pass print(globals()) print(locals())func()print(a)
二、函数的嵌套
1、函数的嵌套调用
在同一命名空间内的函数可以相互调用。假设函数A和B在同一命名空间内,那么可以在A中调用B,也可以在B中调用A。
def A(): print('in func A')def B() print('in func B,call A func next') A() B()
2、函数的嵌套定义
在函数中定义函数。为了叙述方便,称在函数里定义的函数为子函数,孙函数依此类推,定义在全局命名空间的函数为父函数。
def Fatherfunc(): print('in father func') def sonfunc(): print('in son func') def grandsonfunc(): print('in grandson func') grandsonfunc() sonfunc()if __name__ == '__main__': #表示程序的入口,详细的原因将在后面的文章中讲述 Fatherfunc()
3、函数内部变量的作用域
在父函数中定义的变量可以在它的所有后代函数中调用,查看,但是不可以修改其值。
def Fatherfunc(): a = 10 def sonfunc(): print(a) # 10 def grandsonfunc(): print(a)#10 #a=1 grandsonfunc() sonfunc() print(a) #10if __name__ == '__main__': Fatherfunc()
上例代码若将grandsonfunc()中的a=1语句取消注释程序将报错。
4、nonlocal关键字
我们无法在函数中改变全局命名空间中的变量的值,除非使用global关键字声明一个全局变量。同理,如果我们要在函数的后代函数中修改函数的内部变量,需要用nonlocal关键字声明一个函数内的局部变量。
值得注意的是:在某一函数内用nonlocal关键字声明了一个局部变量后,会从当前函数的父函数开始查找这个变量,查询到立即停止,如果找不到再到爷爷函数里去找,直到找到为止。若是在最外层函数也找不到这个变量就会报错。
def Fatherfunc(): a=10 def sonfunc(): nonlocal a print(a) # 10 a = 1 def grandsonfunc(): print(a)#1 grandsonfunc() sonfunc() print(a) #1if __name__ == '__main__': Fatherfunc()
三、闭包函数
首先补充一个小知识。函数名本质上是一个变量,它存储着某一段代码在内存中的地址入口。因此,我们完全可以把函数名当作一般的变量,把它的值赋给其他的变量,放在列表、字典里面等等操作,甚至是当作参数传给另一个函数然后通过变量名()的方式调用函数。
闭包函数:使用了父函数的子函数。
def func(): a = 10 def inner(): print(a)
闭包函数的作用:用于作用域,我们无法直接调用函数内部的函数。而前面已经说过函数名介绍一个变量,于是我们就可以通过return闭包函数的函数名使得可以直接调用闭包函数。
def func(): a = 10 def inner(): print(a) return innerif __name__ == '__main__': f = func() f()#func()执行完的时候,返回inner,inner是函数inner()的代码地址,然后把这个地址返回并赋值给f,此时f相当于inner,f()相当于inner()
同时,我们是可以给inner设置参数,并通过f()传参的。