Python函数之函数II
1.名称空间
-
接下来我们讲的内容,理论性的偏多,就是从空间角度,内存级别去研究python。首先我们看看什么是全局名称空间:
""" 在python解释器开始执行之后, 就会在内存中开辟一个空间, 每当遇到一个变量的时候, 就把变量名和值之间的关系记录下来, 但是当遇到函数定义的时候, 解释器只是把函数名读入内存, 表示这个函数存在了, 至于函数内部的变量和逻辑, 解释器是不关心的. 也就是说一开始的时候函数只是加载进来, 仅此而已, 只有当函数被调用和访问的时候, 解释器才会根据函数内部声明的变量来进行开辟变量的内部空间. 随着函数执行完毕, 这些函数内部变量占用的空间也会随着函数执行完毕而被清空. 我们首先回忆一下Python代码运行的时候遇到函数是怎么做的,从Python解释器开始执行之后,就在内存中开辟里一个空间,每当遇到一个变量的时候,就把变量名和值之间对应的关系记录下来,但是当遇到函数定义的时候,解释器只是象征性的将函数名读如内存,表示知道这个函数存在了,至于函数内部的变量和逻辑,解释器根本不关心。 等执行到函数调用的时候,Python解释器会再开辟一块内存来储存这个函数里面的内容,这个时候,才关注函数里面有哪些变量,而函数中的变量回储存在新开辟出来的内存中,函数中的变量只能在函数内部使用,并且会随着函数执行完毕,这块内存中的所有内容也会被清空。 """
我们给这个‘存放名字与值的关系’的空间起了一个名字-------命名空间。
代码在运行伊始,创建的存储“变量名与值的关系”的空间叫做全局命名空间;
在函数的运行中开辟的临时的空间叫做局部命名空间也叫做临时名称空间。
现在我们知道了,py文件中,存放变量与值的关系的一个空间叫做全局名称空间,而当执行一个函数时,内存中会临时开辟一个空间,临时存放函数中的变量与值的关系,这个叫做临时名称空间,或者局部名称空间。
其实python还有一个空间叫做内置名称空间:内置名称空间存放的就是一些内置函数等拿来即用的特殊的变量:input,print,list等等,所以,我们通过画图捋一下:
现在是两类空间:
还有一个空间叫做内置名称空间:内置名称空间存储的就是内置的所有函数、模块等与值的对应关系。
a = 1 name = 'barry' content = input() s1 = abc
-
么是名称空间?
名称空间就是在内存中开辟一个空间,存储的是变量与值(内存地址)的对应关系
- python中的名称空间分为三种:
- 内置名称空间
- 开启时间:程序运行时,先加载解释器即开辟内置名称空间。
- 空间存储的内容:内置函数、内置模块与值的对应关系。
- 结束时间:程序结束后,解释器在内存中自动释放。
- 全局名称空间
- 开启时间:程序运行时,加载当前py文件时,开辟全局名称空间。
- 空间存储的内容:当前py文件所有的变量与值的对应关系。
- 结束时间:程序结束后,马上结束。
- 临时名称空间
- 开启时间:函数执行时开启。
- 空间存储的内容:函数中所有的变量与值的对应关系。
- 结束时间:函数执行完毕时。
- 内置名称空间
- python中的名称空间分为三种:
2.取值顺序与加载顺序
-
加载顺序
内置名称空间 ------> 全局名称空间 -------> 临时名称空间。
-
取值顺序
满足就近原则
input = 666 print(input) input = 777 def func(): input = 100 print(input) func() # 临时名称空间 ------> 全局名称空间 -------> 内置名称空间 # 单向不可逆。举例:如果在全局名称空间寻找一个变量,先从全局空间找,若没有则从内置空间找,一定不会从临时空间找。
3.高阶函数
函数中嵌套函数,研究他们的执行过程。
-
程序中遇到函数名() 一定会执行此函数,并且此函数不执行完毕之前,代码不会向下执行。
例一 def fun1(): print(111) def fun2(): print(222) fun1() print(555) fun2() # 一定是等到fun2函数执行完毕之后,在向下执行 print(333) # 例二 def func1(): print(111) def func2(): print(222) func1() def func3(): print(333) func2() print(444) func3() print(555) # 例三 def wrapper(): print(777) def inner(): print(111) print(222) print(333) print(555) wrapper() print(666) # 例四 def wrapper(): print(777) def inner(): print(111) print(222) print(333) inner() print(888) print(555) wrapper() print(666) #
4.作用域
-
作用域包含全局作用域以及局部作用域。
-
全局作用域:内置名称空间+全局名称空间。
-
局部作用域:临时名称空间。
-
5.函数名的使用
-
引子
函数名是什么?函数名就是一个变量,这个变量稍微有一些特殊,这个变量指向的数据是此函数的内存地址。
-
函数名指向的函数的内存地址。
def func(): print('in func') print(func) # <function func at 0x10911ce18>
-
函数名就是一个变量。
a = 'barry' print(a.upper()) lst = [1, 2] lst.append(666) print(lst)
-
变量的赋值运算
a = 100 b = a c = b print(c) # 按照上面的两个例子,变量之所以可以调用upper方法,或者是可以调用append方法,是因为他指向的数据的数据类型导致的。 变量可以做什么?是由它指向的数据的数据类型决定的。 def func(): print('in func') func() print(func) f = func a = f b = a b()
-
函数名可以当做容器型数据类型的元素。
def func1(): print('in func1') def func2(): print('in func2') def func3(): print('in func3') lst = [func1, func2, func3] for i in lst: i()
-
函数名可以当做函数的参数。
def func(argv): print(argv) argv.append(666) #def func1(): print('in func1') a = [11, 22, 33] func(a) def func(argv): # print(argv) argv() # func1() def func1(): print('in func1') func1() func(func1)
-
函数名可以当做函数的返回值。
def func(argv): # argv = 'barry' return argv # 'barry' a = 'barry' ret = func(a) # 'barry' print(ret) def func(argv): # argv = login函数的内存地址 return argv # login函数的内存地址 def login(): print('in login') return 666 ret = func(login) # login函数的内存地址 a = ret() # login() print(a) 函数名也称之为叫第一类对象