day10-Python运维开发基础(函数嵌套、nonlocal声明局部变量、闭包、locals/globals、lambda表达式)
1. 函数的嵌套与nonlocal 声明局部变量
# ### 函数的嵌套 """ 函数和函数之间可以互相嵌套: 嵌套在内层的叫做内函数 乔涛在外层的叫做外函数 """ def outer(): def inner(): print("我是inner函数 ... ") inner() # (1)内部函数可以直接在函数外部调用么 不行 # inner() # (2)调用外部函数后,内部函数可以在函数外部调用吗 不行 # outer() # inner() # (3)内部函数可以在函数内部调用吗 可以 # outer() # (4)内部函数在函数内部调用时,是否有先后顺序 有的 先定义在调用 # 定义三个函数 outer函数中有inner ,inner函数中有smaller, 调用smaller def outer(): def inner(): def smaller(): print(id) print("我是smaller函数") smaller() inner() outer() #找寻变量的调用顺序采用LEGB原则(即就近原则) """ B —— Builtin(Python);Python内置模块的命名空间 (内建作用域) G —— Global(module); 函数外部所在的命名空间 (全局作用域) E —— Enclosing function locals;外部嵌套函数的作用域(嵌套作用域) L —— Local(function);当前函数内的作用域 (局部作用域) 依据就近原则,从下往上 从里向外 依次寻找 """
# ### nonlocal 用来修饰局部变量 """ nonlocal 符合LEGB原则 (1)用来修改当前作用域上一级的局部变量 (2)如果上一级没有,在向上一级依次寻找 (3)如果再也找不到了,直接报错 """ # (1)用来修改当前作用域上一级的局部变量 def outer(): a = 13 def inner(): nonlocal a a = 15 print(a) inner() print(a) outer() # (2)如果上一级没有,在向上一级依次寻找 # b = 200 def outer(): b = 100 def inner(): b = 200 def smaller(): nonlocal b b = 101 print(b) smaller() print(b) inner() print(b) outer() # (3)如果再也找不到了,直接报错 """ b =200 def outer(): def inner(): def smaller(): # nonlocal 只修改局部变量 nonlocal b b +=10 smaller() print(b) inner() outer() """ # (4)不通过nonlocal , 是否可以修改局部变量 def outer(): lst = [1,2,3] def inner(): lst[-1] += 10 inner() print(lst) outer()
2. 闭包函数
# ### 闭包函数 """ 生命周期从长到短: 内置空间变量 -> 全局空间变量 -> 局部空间变量 内置空间变量 : 在解释器退出之后,就会释放空间 全局空间变量 : 在文件执行结束之后,就会释放空间 局部空间变量 : 在调用完函数之后,就会释放空间 定义: 内函数使用了外函数的局部变量,外函数把内函数返回出来的过程,叫做闭包,这个内函数叫做闭包函数 """ # (1) 基本语法 def zouyongling_family(): father = "王健林" def hobby(): print("先定一个小目标,比如挣他一个亿,这是我爸爸%s说的" % (father)) return hobby func = zouyongling_family() # func = hobby func() # 获取闭包函数使用的变量 __closure__ , cell_contents(了解) # __closure__ 获取单元格对象,这个对象中含有延长生命周期的变量值 tup = func.__closure__ print(tup) # (<cell at 0x00000226506595E8: str object at 0x00000226506EC450>,) print(tup[0]) # <cell at 0x00000226506595E8: str object at 0x00000226506EC450> # cell_contents 这个属性 可以获取单元格对象中的值,如果有证明是一个闭包,如果没有,就不是一个闭包 print(tup[0].cell_contents) # (2) 升级闭包函数 """ 特点:内函数使用了外函数的局部变量,该局部变量与内函数发生绑定,延长该变量的生命周期 """ def huanglexi_family(): jiejie = "马蓉" meimei = "马诺" money = 1000 def jiejie_hobby(): nonlocal money money -= 700 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 = huanglexi_family()# func = big_master print(func) tup = func() # big_master() => tup = (jiejie_hobby,meimei_hobby) print(tup) # (<function huanglexi_family.<locals>.jiejie_hobby at 0x000001425AE73BF8>, <function huanglexi_family.<locals>.meimei_hobby at 0x000001425AE7C158>) # 获取闭包函数 jiejie_hobby = tup[0] meimei_hobby = tup[1] # 调用函数 jiejie_hobby() meimei_hobby()
# ### 闭包的特点: """ 内函数使用了外函数的局部变量,该变量与内函数发生绑定,延长该变量的生命周期 """ def outer(val): def inner(num): return val + num return inner func = outer(10) # func = inner res = func(5) # val + num = 15 print(res) """ 代码解析: outer(10) val = 10 func = inner func(5) num = 5 return val + num => return 10 + 5 => 15 print(res) => 15 """ # ### 闭包的意义 """ 闭包可以优先使用外函数中的变量,并对闭包中的值起到了封装保护的作用.外部无法访问. """ # 记录鼠标点击次数操作 # 方法一 : 全局变量的作用范围太大,容易被串改 total = 0 def click(): global total total += 1 print(total) click() # 1 click() # 2 click() # 3 click() # 4 total = 100 click() # 方法二 : def myclick(): x = 0 def click(): nonlocal x x += 1 print(x) return click func = myclick() print(func) func() # 1 func() # 2 func() # 3 func() # 4 x = 100 func()
3. locals 与 globals、lambda表达式(匿名函数)
# ### locals 和 globals """ -- globals() :返回字典,存放着全局作用域所有内容 -- locals() :返回字典,当前作用域所有内容 """ # (1)locals """ 在函数外,获取locals打印之前所有变量内容,形成字典,获取全局作用域的内容 在函数内,获取locals调用之前所有变量内容,形成字典,获取局部作用域的内容 """ # 在函数外 """ a = 1 b = 2 res = locals() c = 3 print(res) """ # 在函数内 """ def func(): a = 1 b = 2 res = locals() c = 3 print(res) func() """ # (2)globals """ 在函数外,获取globals打印之前所有变量内容,形成字典,获取全局作用域的内容 在函数内,获取globals调用之前所有变量内容,形成字典,获取全局作用域的内容 """ # 在函数外 """ a = 1 b = 2 res = globals() c = 3 print(res) """ a1 = 1 b1 = 2 # 在函数内 def func(): a = 1 b = 2 res = globals() c = 3 print(res) c1 = 3 func() d1 = 4 # globals 可以动态的创建变量 # 声明变量 wangwen = "真靓" # globals 创建一个全局变量 : 返回的是全局字典,通过在字典中添加键值对,来动态创建变量,键就是变量名,键所对应的值也是这个变量的值 """ dic = globals() print(dic) dic["yangmazi"] = "真聪明" print(yangmazi) """ # globals 创建多个全局变量 """动态创建p1~p5 5个变量""" def func(): dic = globals() print(dic) for i in range(1,6): dic[ "p%d" % (i) ] = i func() """ "p%d" % (1) => "p1" "p%d" % (2) => "p2" "p%d" % (3) => "p3" "p%d" % (4) => "p4" "p%d" % (5) => "p5" """ print(p1,p2,p3,p4,p5)
# ### 匿名函数 : lambda表达式 """ 用一句话来表达只有返回值的函数 特点: 简洁 , 高效 语法: lambda 参数 : 返回值 """ # (1)没有参数的lambda 表达式 def func(): return "我是func函数 ... " # 改写 func = lambda : "我是func函数 ... " res = func() print(res) # (2)有参数的lambda 表达式 def func(n): return type(n) # 改写 func = lambda n : type(n) res = func(4.56) print(res) # (3)带有判断条件的lambda 表达式 def func(n): if n % 2 == 0: return "偶数" else: return "奇数" res = func(3) print(res) # 三目运算符 """ 真区间值 if 条件表达式 else 假区间值 如果条件表达式满足, 就返回真区间值 否则,就返回假区间值 """ def func(n): return "偶数" if n % 2 == 0 else "奇数" res = func(3) print(res) # 改写 func = lambda n : "偶数" if n % 2 == 0 else "奇数" res = func(20) print(res) # 比较两个数的大小,返回最大值 def func(x,y): if x>y: return x else: return y # lambda 改写 func = lambda x,y : x if x>y else y res = func(3,2) print(res)
day10