locals和globals,函数的嵌套,nonlocal,闭包函数及特点以及匿名函数---day11
1.locals和globals
1.1locals 获取当前作用域中的所有内容
locals 如果在函数外,调用locals(),获取打印的是打印之前的所有变量,返回字典,全局空间作用域 locals 如果在函数内,调用locals(),获取的是调用之前的所有变量,返回字典,局部空间作用域 #例子1 a = 1 b = 2 res = locals() c = 3 print(res) #打印前面所有的变量的值,返回一个字典 d = 4 #不打印 a = 1 def outer(): def inner(): return 'www' inner() res = locals() b = 2 c = 4 print(res) #打印前面所有全局变量,返回一个字典 d = 5 #不打印 #例子2 a = 1 def func(): b = 2 #这个是调用之前的局部变量 res =locals() #这个是调用 c = 3 print(res)#打印的是调用之前的局部内的变量是b = 2,返回字典形式{'b':2}, d = 4 func() a = 1 def outer(): b = 2 #不会打印外函数的局部变量b=2 def inner(): c = 4 #内函数的局部变量 e = 6 #内函数的局部变量 res = locals() 调用 d =4 print(res) # 打印内函数的局部变量返回{'c':4,'e':6} inner() outer()
1.2globals 获取全局作用域的所有内容
globals 如果在函数外,调用globals(),获取打印的是打印之前的所有全局变量,返回字典,全局空间作用域 globals 如果在函数内,调用globals(),获取打印的是调用之前的所有全局变量,返回字典,全局空间作用域 #例子3 a = 5 b = 6 res = globals() c = 7 print(res) #打印之前的所有变量 返回字典形式 d = 8 #不打印 该变量在打印之后 a = 1 def outer(): def inner(): return 'www' inner() res = globals() b = 2 c = 4 print(res) #打印前面所有全局变量,返回一个字典 d = 5 #不打印 #例子4 a = 10 #全局变量 def func(): b = 11 c =12 res = globals() #调用 d = 13 print(res)#打印出的是调用之前的所有全局变量{'a':10,'ff':33} ff = 33 #全局变量 func() #执行函数 zz = 50 #不打印,因为这是在整个func函数全部执行完才定义的全局全局变量
1.3globals返回的是系统的字典
#1.正常方式定义变量 zhangsan = '112233' #2.通过系统的全局字典添加键值对,可以动态创建全局变量 dic =globals() print(dic) ##{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000000001DEA2B0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/pythonproject/python_all/ceshi/day_01.py', '__cached__': None, 'dic': {...}} # 传递字符串 ,创建一个变量 k = 'liuwei' dic[k] = '刘伟' #键值对添加'liuwei':'刘伟' print(liuwei) #通过键取值 #3.批量创建全局变量 在函数中 def func(): dic = globals() for i in range(1,6): dic['p%d'%(i)] = i #p1 p2 p3 p4 p5 p6 func() print(p1) #1 print(p2) #2 print(p3) #3 print(p4) #4 print(p5) #5
2.函数的嵌套
函数的嵌套: 嵌套在函数的外边叫作外函数 嵌套在函数的里面叫作内函数 def outer(): def inner(): print('我是inner 函数') inner() outer() #inner() (1)内部函数可以直接在函数外部调用吗? 不可以 (2)调用外部函数后,内部函数可以在函数外部调用吗? 不可以 (3)内部函数可以在函数内部调用吗? 可以 (4)内部函数在函数内部调用时,是否由先手顺序? 有(必须先定义再调用) #最外层outer,中间层inner,最里层smaller,调用smaller,执行里面的代码 def outer(): def inner(): def smaller(): print(id) #找的是内置的 print('我是smaller函数') smaller() inner() outer() # LEGB 原则(即就近找变量的原则) #找寻变量的调用顺序采用LEGB原则(就近原则) ''' B —— Builtin(Python) python内置模块的命名空间(内键作用域) G —— Global(module) 函数外部所在的命名空间 (全局作用域) E —— Enclosing function locals;外部嵌套函数的作用域 (嵌套作用域) L —— Local(function); 当前函数内的作用域 (局部作用域) 依据就近原则,从下往上 从里向外,依次寻找 '''
3.nonlocal
nonlocal 关键字 用来更改局部变量 nonlocal 遵循LEGB原则 (1)nonlocal 专门用来修改当前作用域上一级的局部变量 (2)如果上一级找不到,那么就继续向上寻找 (3)全部找不到,直接报错 (不涉及全局变量) #(1) nonlocal 专门用来修改当前作用域上一级的局部变量 def outer(): a = 10 def inner(): nonlocal a a = 20 inner() print(a) #a = 20 outer() #(2) 如果上一级找不到,那么久继续向上寻找 '''nonlocal 只能修改局部变量''' def outer(): a = 41 def inner(): def smaller(): nonlocal a a = 42 print(a) smaller() print(a) #42 inner() print(a) #42 outer() #(3) 全部找不到,直接报错 a = 41 def outer(): def inner(): def smaller(): nonlocal a #找不到局部变量a 报错 print(a) smaller() print(a) inner() print(a) outer() #(4) 不使用nonlocal 是否可以修改局部变量呢? def outer(): lst = [1,2,3] def inner(): lst[-1] = 52 inner() print(lst) outer() #当局部中有可变数据类型时,可以不使用nonlocal来修改全局变量 def outer(): dic = {'a'1,'b':2} def inner(): dic['a'] = 5 inner() print(dicvar) outer() #注意点 两者之间的区别 #第一种 这种是在函数内修改局部变量 def outer(): a = 10 def inner(): nonlocal a a = 2 print(a) #a = 2 inner() print(a) # a = 2 outer() #第二种 这种是在函数内自己又定义了一个变量a,与外函数的局部变量不是同一个 def outer(): a = 10 def inner(): a = 2 print(a) # a = 2 inner() print(a) # a = 10 outer()
4.闭包函数
闭包函数: 闭包函数: 内函数使用了外函数的局部变量 外函数将内函数返回出来的过程 叫作闭包 里面的内函数叫作闭包函数 #(1) 闭包函数用法 def wz_family(): father = '马云' def mayun_hobby(): print('{0}不在乎钱'.format{father}) return mayun_hobby # res = mayun_hobby <====> res() = mayun_hobby() res = wz_family() print(res) #打印出来的是一个函数内存地址 res() #加括号相当于调用函数 解析: wz_family调用函数拿一个变量res接收,返回mayun_hobby,res = mayun_hobby, 内部函数mayun_hobby需要mayun_hobby加()执行,就可以用res()执行内部函数 #(2) 升级 def liuwei_familt(): father = '刘德华' jiejie = '刘亦菲' meimei = '杨颖' money = 1000 def jiejie_hobby(): nonlocal money money -= 600 print('穷的没钱了,还剩%s元'%(money)) def meimei_hobby(): nonlocal money money -=200 print('我比你还穷,只剩下%s元'%(money)) def big_master(): return [jiejie_hobby,meimei_hobby] return big_master func = liuwei_familt() #返回的big_master print(func) res = func() #相当于调用了big_master() print(res) #返回回来的是[jiejie_hobby,meimei_hobby] #分别获取姐姐,妹妹这两个函数 jiejie = res[0] jiejie() #相当于调用jiejie_hobby函数 meimei =res[1] meimei()#相当于调用meimei_hobby函数 # ### 获取闭包函数使用的变量 __closure__,cell_contents(了解) tup = func.__closure__ print(tup) #(<cell at 0x0000000001E15618: function object at 0x0000000001E99AE8>, # <cell at 0x0000000001E15678: function object at 0x0000000001E99B70>) #cell_contents #功能获取单元对象里面的内容 jiejie = tup[0].cell_contents meimei = tup[1].cell_contents print(jiejie) #<function weifuqiang_family.<locals>.jiejie_hobby at 0x0000000001E99AE8> jiejie() meimei()
5.闭包特点
闭包特点: 内函数使用了外函数的局部变量,该局部变量与内函数发生绑定,延长该变量的生命周期 #函数的定义处 def outer(var): #var = 5 def inner(num): return num+var #num = 4 return inner # 函数的调用处 func = outer(5) res = func(4) # ==> inner() print(res) 解析: 1.实参5 和形参var一一对应 进行接收val = 5 因为内函数inner 和 val进行绑定,延长了val变量的生命周期,不释放 func = outer(5) <====> func = inner 2,实参4 和形参num一一对应 进行接收num= 4 return num + val <===> 4+5 = 9 闭包的意义 闭包可以优先使用外函数的局部变量 局部变量在函数外部不能被直接使用 对局部变量实现了保护的作用,外部无法访问 #模拟鼠标点击操作 #方法一 click_num = 0 def click_func(): global click_num click_num +=1 print(click_num) click_func() #1 click_func() #2 click_func() #3 click_num = 100 #在函数内部声明click_num为全局变量并修改,所以在函数外部也可以修改这个全局变量 click_func() #101 #方法二 def outer(): click_num = 0 def inner(): nonlocal click_num #定义click_num是一个局部变量,在函数局部内有这个变量 click_num +=1 print(click_num) return inner #click_func = inner click_func = outer() click_func() #1 click_func() #2 click_func() #3 click_num = 100 #在函数外部不能修改局部内变量 click_func() #4 解析: 闭包函数: 首先外函数的局部变量click_num为0,内函数想修改外函数的局部变量就需要用nonlocal声明 然后才能修改 click_num = 100在函数外部不能修改函数内部的局部变量
6.匿名函数
匿名函数 lambda 表达式 用一句话来表达只有返回值的函数 特点:简洁,高效,方便 语法结构: lanbda 参数:返回值 #(1) 无参的lambda表达式 def func(): return '我是大哥' #改成lambda表达式 func = lambda : '我是大哥' res = func() print(res) #(2) 有残的lambda 表达式 def func(n): return type(n) #用lambda表达式 func = lambda n : type(n) res =func() print(res) #(3) 带有判断条件的lambda表达式 def func(n): if n%2 == 0: return '偶数' else: return '奇数' 三元(三目)运算符 真值 if 条件表达式 else 假值 如果条件表达式成立 为真 返回真值 如果条件表达式不成立 为假 返回假值 n = 20 res '偶数' if n%2 == 0 else '奇数' print(res) #lambda表达式 func = lambda n : '偶数' if n %2==0 else '奇数' res = func() print(res) #练习 def func(x,y): if x>y: return x else: return y func = lambda x,y : x if x>y else y res = func(22,5) print(res)
总结:今天主要讲了以下个点,locals和globals的用法,函数的嵌套,nonlocal,闭包函数及其特点以及匿名函数
locals:获取当前作用域中的所有内容
locals 如果在函数外,调用locals(),获取的是打印之前的所有变量,返回字典,全局空间作用域
locals 如果在函数内,调用locals(),获取的是调用之前的所有变量,返回字典,局部空间作用域
globals 获取全局作用域的所有内容
globals 如果在函数外,调用globals(),获取的是打印之前的所有全局变量,返回字典,全局空间作用域
globals 如果在函数内,调用globals(),获取的是调用之前的所有全局变量,返回字典,全局空间作用域
用globals可以通过系统的全局字典添加键值对,可以动态创建全局变量,也可以批量创建全局变量
函数的嵌套:
嵌套在函数的外边叫作外函数
嵌套在函数的里面叫作内函数
内部函数不可以直接在函数外部调用
调用外部函数后,内部函数不可以在函数外部调用
内部函数可以在函数内部调用
内部函数在函数内部调用时,有先后顺序(必须先定义再调用)
还讲了LEGB原则就是就近变量的原则,从下往上,从里向外
nonlocal 通用遵循LEGB原则:
专门用来修改当前作用域上一级的局部变量
如果上一级找不到,那么就继续向上寻找
全部找不到,直接报错 (不涉及全局变量)
不使用nonlocal可以修改局部变量,当外函数的局部变量是可变数据类型时,内函数可以不用nonlocal来修改局部变量
闭包函数:
内函数使用了外函数的局部变量
外函数将内函数返回出来的过程 叫作闭包
里面的内函数叫作闭包函数
还讲了两个获取闭包函数的函数,__closure__,cell_contents
闭包的特点:
内函数使用了外函数的局部变量 该局部变量与内函数发生绑定 延长该变量的生命周期
闭包可以优先使用外函数的局部变量
局部变量在函数外部不能被直接使用
对局部变量实现了保护的作用,外部无法访问
匿名函数:用一句话来表达只有返回值的函数 特点:简洁,高效,方便
语法结构:
lanbda 参数:返回值
三元运算符:
真值 if 条件表达式 else 假值
如果条件表达式成立 为真 返回真值
如果条件表达式不成立 为假 返回假值
-------------------------------------------
个性签名:代码过万,键盘敲烂!!!
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!