我们首先回忆一下Python代码运行的时候遇到函数是怎么做的,从Python解释器开始执行之后,就在内存中开辟里一个空间,每当遇到一个变量的时候,就把变量名和值之间对应的关系记录下来,但是当遇到函数定义的时候,解释器只是象征性的将函数名读如内存,表示知道这个函数存在了,至于函数内部的变量和逻辑,解释器根本不关心。
等执行到函数调用的时候,Python解释器会再开辟一块内存来储存这个函数里面的内容,这个时候,才关注函数里面有哪些变量,而函数中的变量回储存在新开辟出来的内存中,函数中的变量只能在函数内部使用,并且会随着函数执行完毕,这块内存中的所有内容也会被清空。
我们给这个‘存放名字与值的关系’的空间起了一个名字-------命名空间。
代码在运行伊始,创建的存储“变量名与值的关系”的空间叫做全局命名空间;
在函数的运行中开辟的临时的空间叫做局部命名空间。
在python中,名称空间三种:
- 全局名称空间
- 局部名称空间(临时)
- 内置名称空间
作用域:
- 全局作用域:作用于全局名称空间 内置名称空间
- 局部作用域:作用于局部名称空间(临时)
取值顺序:就近原则,单向从小到大范围
局部名称空间 ---> 全局名称空间 ---> 内置名称空间
加载顺序
内置名称空间 ---> 全局名称空间(当程序执行时) ---> 局部名称空间(当函数调用的时候)
局部名称空间 对全局名称空间的变量可以引用,但是不能改变。
如果你在局部名称空间对一个变量进行修改,那么解释器会认为你的这个变量在局部中已经定义了。
global
- 1.在局部名称空间声明一个全局变量
- 2.在局部名称空间可以对全局变量进行修改
实际中
不常用
nonlocal
- 相当于子函数对父函数的变量进行修改。
- 此变量不能是全局变量
- # 在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,
- # 并且引用的哪层,从那层及以下此变量全部发生改变。

# global # 1,在局部名称空间声明一个全局变量。 # def func2(): # global name # name = 'alex' # func2() # print(name) # 2,在局部名称空间可以对全局变量进行修改。 # count = 1 # def func1(): # global count # count = count + 1 # print(count) # func1() # print(count)

# nonlocal # def func1(): # count = 666 # def func2(): # print(count) # func2() # func1()
函数嵌套
def func1(): count = 666 def inner(): print(count) def func2(): nonlocal count count += 1 print('func2',count) func2() print('inner',count) inner() print('func1',count) func1() # 666 func2 667 inner 667 func1 667
函数名的应用:
- 1. 函数名就是函数的内存地址
- 2. 函数名可以做为变量
- 3. 函数名可以做为函数的参数
- 4. 函数名可以当作函数的返回值
- 5. 函数名可以做为容器类类型的元素
像上面的函数名这种,叫第一类对象
- 1. 可在运行期创建
- 2. 可用作函数参数或返回值
- 3. 可存入变量的实体。
1. 函数名就是函数的内存地址 # def func1(): # print(666) # # print(func1) #<function func1 at 0x0000028BEC62C1E0> # 2. 函数名可以做为变量 # f1 = func1 # f1() # 3. 函数名可以做为函数的参数 # def func1(): # print(666) # # def func2(x): # x() # func1() # # func2(func1) # 4. 函数名可以当作函数的返回值 # def wraaper(): # def inner(): # print('----inner ') # return inner # # ret = wraaper() # inner # ret() # # def func2(): # print('in the func2') # # def func3(x): # print('in the func3') # x = func2 # return x # # f1 = func3(func2) # func2 # f1() # 5. 函数名可以做为容器类类型的元素 # def func1(): # print('in func1') # # def func2(): # print('in func2') # # def func3(): # print('in func3') # # l1 = [func1, func2, func3, ] # for i in l1: # i() # 像上面的函数名这种,叫第一类对象
globals() 返回全局变量的一个字典
locals() 返回当前位置的局部变量的字典
# globals() locals() # def func1(): # pass # print(globals()) # print(locals()) def func1(): a = 2 b = 3 print(globals()) print(locals()) func1()
闭包: 内层函数对外层函数的变量(非全局变量)的引用,并返回, 这样就形成了闭包。
闭包的作用:
当程序执行时,遇到了函数执行,他会在内存中开辟一个空间,局部名称空间。如果这个函数内部形成了闭包,
那么他就不会随着函数的结束而立马消失。
# def wrapper(): # name = 'alex' # def inner(): # print(name) # print(inner.__closure__) # 判断是否闭包(<cell at 0x00000181FD0ED8E8: str object at 0x00000181FD00CE68>,) # # 不是闭包返回None # inner() # return inner # # wrapper() name = 'alex' def wrapper(n): # 相当于 n = 'alex' def inner(): print(n) print(inner.__closure__) # 闭包 inner() return inner wrapper(name)