一、命名空间:
什么是命名空间:
--> Python代码在执行的过程中从上到下顺序执行,
--> 从python解释器开始执行之后,就在内存中开辟了一个空间。
--> 每当遇到一个变量的时候,就把变量名和值之间的对应关系记录下来。
--> 但是,当遇到函数的时候,Python解释器只是将函数名称读入内存,并且知道这个函数已经存在了,此时,函数内部的变量和逻辑关系解释器根本就不关心,并没有执行函数内部的代码
--> 等到执行函数的调用的时候,Python解释器才会在内存中再开辟一块儿空间,来存储函数里面的代码内容,这个时候,才会关注函数内部有哪些变量。函数内部的变量存储在新开辟的空间中,只能供函数内部使用,等函数执行完毕,这块儿内存空间中所有内容都会被清空。
--> 我们给这个“存放名字与值的关系”的空间起了一个名字——叫做命名空间
命名空间分为三种:全局命名空间,局部命名空间,内置命名空间。
1.首先先说下内置命名空间:里面包含了Python解释器为我们提供的一些名字。比如:input,print,list,tuple等等。我们直接拿过来用就可以。
2.全局命名空间:代码在运行伊始,创建的存储“变量名与值的关系”的空间叫做全局命名空间。
3.局部命名空间:在函数的运行中开辟的临时的空间叫做局部命名空间。
命名空间的加载顺序:内置命名空间(程序运行前加载)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程序运行中:调用时才加载)
关于作用域:作用域就是作用范围,按照生效范围可以分为全局作用域和局部作用域。
全局作用域:包含内置命名空间和全局作用空间,在整个文件的任意位置都能被引用、全局有效
局部作用域:局部名称空间,只能在局部范围内使用
关于global关键字
来看一段代码:
a = 1 def func(): a = 20 print(a) func() print(a)
上面的代码打印结果
1 1
第一个 print(a)在调用函数之前打印 a 的值,打印 1 ,后面调用函数,在函数内部,明明已经修改了 a的值,后面打印 还是打印 1 。其实,第一个 a = 1.这个a 是全局命名空间。在函数内部 a = 20 ,这个a是局部命名空间,如果想在函数内部,对全局变量的值做修改,可以使用关键字 global
a = 1 def func(): global a a = 20 print(a) func() print(a)
这次的打印结果
1 20
二、关于函数的探讨
先看一段代码:
def func(): # 定义一个函数 pass f = func # 将函数名称赋值给一个变量 print(func) # 打印函数名称 print(f) # 打印变量 f
执行结果
<function func at 0x000000000050C1E0> # 翻译结果:0x000000000050c1e0处的函数func <function func at 0x000000000050C1E0>
从结果中可以看出:函数名称实际上存放的是这个函数的一个内存地址,另外,函数名也可以赋值给一个变量,其实函数名也是一个变量
既然函数名本质上其实就是一个变量,那么,函数名也就可以作为容器中的一个元素。如:
def func1(): pass def func2(): pass def func3(): pass list_func = [func1,func2,func3] for l_func in list_func: print(l_func)
打印结果
<function func1 at 0x00000000003DC1E0> <function func2 at 0x0000000002718510> <function func3 at 0x0000000002718598>
也可以当做函数的参数以及返回值
def outer(): name = 'jack' def inner(): print(name) return inner outer()
三、闭包:内部函数包含对外部作用域而非全剧作用域名字的引用,该内部函数称为闭包函数
来看一段代码
def outer(x): def inner(y): return x + y print(inner.__closure__) # 使用__closure__ 判断是否为闭包,如果输出包含cell 则是闭包。如果输出为None 则不是闭包 return inner f = outer(9) print(type(f)) # 打印f的类型 print(f.__name__) # 输出 f 的名字
输出结果
(<cell at 0x00000000021DB858: int object at 0x000007FEDFC5D520>,) <class 'function'> inner
结合这段简单的代码和定义来说明闭包:
如果在一个内部函数里:inner(y)就是这个内部函数,对外部作用域(但不是在全局作用域)的变量进行引用:x就是被引用的变量(x在外部作用域outer里面,但是不是全局作用域),name这个内部函数就是一个闭包
使用闭包的注意事项:
在闭包中,是不能修改外部作用域的变量的值
def outer(): a = 0 def inner(): a = 1 print(a) print(a) inner() return inner outer()
打印结果
0
1
另外需要注意的一点是:闭包不要引用任何的循环变量,或者后续会发生变化的变量