Day10 of learning python--函数初阶与闭包
1.为什么要使用函数
因为函数的可读性强,而且复用性强
2.函数的定义格式
def 函数名():
函数体
return 返回值
1 def func(): 2 a = 2 3 return a #可有可不有 4 b = func() #函数的调用 5 print(b)
注意:所有的函数,只定义不调用就一定不执行,先定义后调用,并且只有调用了函数,才会执行函数体的d代码。
3.默认参数的陷阱
1 def qqxing(l=[]) # 默认参数相当于在函数外面定义了一个变量 2 l.append(1) 3 print(l) 4 5 qqxing() #[1] 6 qqxing() #[1,1] 7 qqxing() #[1,1,1] 8 # 如果默认参数的值是一个可变的数据类型 9 # 那么每一次调用函数的时候,如果不传值就公用这个数据类型的资源
4.命名空间
全局命名空间--我们写的代码但不是函数中的代码,是在程序从上到下被执行的过程中依次加载进内存的,放置了我们设置的所有变量名和函数名
局部命名空间--就是函数内部定义的名字,当调用函数的时候,才会产生这个名称空间,随着函数执行的结束,这个命名空间就又消失了
内置命名空间--python解释器,就是python解释器一启动就可以使用的名字(print,input,list,tuple)存储在内置命名空间中,内置的名字在启动解释器的时候就被加载在内存里
在局部:可以使用全局、内置命名空间中的名字
在全局:可以使用内置命名空间中的名字,不能使用局部的名字
在内置:不能使用局部和全局的名字
注意:当我们在全局定义了和内置名字空间中同名的名字时,会使用全局的名字,在正常的情况下,直接使用内置的名字,当我自己有得时候,我就不找我得上级要,如果没有,就找上一级要了,继续找,没有就报错。
1 a = 1 2 b = 2 3 def wa(): 4 x = 'aaa' 5 b = 'bbb' 6 print(locals()) 7 8 wa() 9 print(globals()) 10 print(locals()) # 本地的 11 # globals永远打印全局的名字 12 # locals输出什么根据local所在的位置
输出:
{'x': 'aaa', 'b': 'bbb'}
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002763BAB6390>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/testfile/test1/Day10/04 测试.py', '__cached__': None, 'a': 1, 'b': 2, 'wa': <function wa at 0x000002763BA6D268>}
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002763BAB6390>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/testfile/test1/Day10/04 测试.py', '__cached__': None, 'a': 1, 'b': 2, 'wa': <function wa at 0x000002763BA6D268>}
5.函数的嵌套
在函数内部定义函数
1 def the_max(a,b,c): # 函数的嵌套调用 2 z = max(a,b) 3 return max(z,c) 4 5 def max(a,b): 6 return a if a > b else b 7 8 print(the_max(1,2,3))
函数的嵌套定义,内部函数可以使用外部函数的定义
1 def outer(): 2 a = 1 3 def inner(): 4 nonlocal a #声明了一个上面第一层上层局部变量 5 a += 1 # 不可变数据类型的修改 6 print(a) 7 print('inner') 8 inner() 9 outer() 10 11 # nonlocal 只能用于局部变量 找上层中离当前最近一层的局部变量 12 # 声明了nonlocal的内部函数的变量修改会影响到 离当前函数最近一层的局部变量 13 # 对全局无效,也只是对最近的一层有效
1 a = 1 2 def outer(): 3 a = 1 4 def inner(): 5 b = 2 6 def inner2(): 7 nonlocal a 8 a += 1 9 inner2() 10 print('###a###:',a) 11 inner() 12 print('***a***:',a) 13 14 outer() 15 print('全局:',a)
结果:
###a###: 2
***a***: 2
全局: 1
6.函数名的使用
func --> 指向函数得内存地址
函数名() -->函数调用
函数得内存地址() -> 函数调用
函数名:第一类对象
1.可在运行期创建
2.可用作为函数参数或返回值
3.可存入变量的实体
1 def func(): 2 print(123) 3 4 # func 函数名就是内存地址 5 func2 = func 6 func2() 7 8 l = [func,func2] #函数名可以作为容器类型的元素 9 print(l) 10 for i in l: 11 i() 12 13 def wa(f): 14 f() 15 return f # 函数可以作为函数的返回值 16 17 qqxing = wa(func2) #函数名可以作为函数的参数 18 print(qqxing)
7.闭包
使用的意义是,不用重复的为变量创建空间,节省内存。
1 #闭包:嵌套函数,内部函数调用外部函数的变量 2 def outer(): 3 a = 1 4 def inner(): 5 print(a) 6 print(inner.__closure__) 7 outer()
结果:(<cell at 0x0000020A92B6D948: int object at 0x00007FF92D75D420>,),有个cell自得就是闭包
1 # import urllib # 模块 2 from urllib.request import urlopen 3 # ret = urlopen('http://www.xiaohua100.cn/index.html').read() 4 # print(ret) 5 def get_url(): 6 url = 'http://www.xiaohua100.cn/index.html' 7 def get(): 8 ret = urlopen(url).read() 9 print(ret) 10 return get 11 12 get_func = get_url() 13 get_func()
8.作用域
全局作用域 -- 作用在全局 -- 内置和全局空间中得名字都属于全局作用域 --globals()
对于不可变数据类型 在局部可查看全局作用域中得变量,但是不能修改
如果想要修改,需要在函数体中一开始添加global声明
如果在一个局部内(函数)内声明了一个global变量,那么这个变量在局部得所有操作将对全局的变量有效
局部作用域 -- 作用在局部 --函数(局部名字空间中得名字属于局部作用域) --locals()
浙公网安备 33010602011771号