一、概念
""" 如果内函数使用了外函数的局部变量, 并且外函数把内函数返回出来的过程,叫做闭包 里面的内函数是闭包函数 """
二、基本语法
def songyunjie_family(): father = "王健林" def f_hobby(): print("我们先顶一个小目标,比如赚它一个亿,这是我爸爸{}".format(father)) return f_hobby func = songyunjie_family() func() obj = func.__closure__[0] print(obj.cell_contents,"<111>")
三、复杂版本
def mashengping_family(): father = "马云" jiejie_name = "aa" meimei_name = "bb" money = 1000 def jiejie(): nonlocal money money -= 700 print("还剩下{}元".format(money)) def meimei(): nonlocal money money -= 200 print("还剩下{}元".format(money)) def big_master(): return (jiejie,meimei) return big_master func = mashengping_family() print(func) # 返回的是元组 tup = func() # big_master() print(tup) # tup = (jiejie,meimei) # 获取姐姐 jiejie = tup[0] # jiejie 函数 # 获取妹妹 meimei = tup[1] # meimei 函数 # big_master 是闭包函数,是直接被mashengping_family返回出来的 # jiejie,meimei 是通过big_master间接被返回到函数外面的 # 调用妹妹 meimei() # 调用妹妹函数 # 调用姐姐 jiejie() # 调用姐姐函数 #看它是不是闭包函数,是就可以用 # cell获取单元格对象结果是一个函数名 # 加() 运行 # ### 获取闭包函数使用的变量 __closure__ res = func.__closure__ print(res,"<222>") # cell_contents 用来获取单元格对象当中的闭包函数 jiejie = res[0].cell_contents meimei = res[1].cell_contents # 通过获取单元格对象 -> 获取单元格对象中的内容 -> 实际的调用 jiejie() meimei() print(jiejie.__closure__[0].cell_contents) print(meimei.__closure__[0].cell_contents)
四、闭包的特征和意义
1、特征
""" 内函数使用了外函数的局部变量 那么该变量与闭包函数发生绑定, 延长该变量的生命周期 """
def outer(val): def inner(num): return val + num return inner func = outer(10) # func = inner res = func(15) # res = func(15) = inner(15) print(res) """ 10实参 -> val 形参 因为内函数inner是闭包函数,使用了外函数val 那么该变量val生命周期被延长,没有随着函数调用的结束而释放. func(15) 把15这个参数赋值给num这个形参 res = inner(15) => return val + num =>10 + 15 => 25 """
2、意义
引入:
# 模拟鼠标点击次数 num = 0 def click_num(): global num num += 1 print(num) click_num() click_num() click_num() num = 100 click_num() click_num()
2.1 使用闭包函数改写点击次数
闭包的意义:闭包可以优先使用外函数中的变量,并对闭包中的值起到了封装保护的作用.外部无法访问.
def click_num(): num = 0 def func(): nonlocal num num += 1 print(num) return func func = click_num() func() func() num = 1000 func() func() func() func() func()
五、匿名函数
1 用一句话来表达只有返回值的函数
"""语法:lambda 参数 : 返回值 """ """追求代码:简洁,高效"""
1、无参的lambda表达式
def func(): return "123" # 改写 func = lambda : "123" res = func() print(res)
2、有参的lambda 表达式
def func(n): return type(n) # 改写 func = lambda n : type(n) print( func([1,2,3]) )
3、带有判断条件的lambda 表达式
def func(n): if n % 2 == 0: return "偶数" else: return "奇数" func = lambda n : "偶数" if n % 2 == 0 else "奇数" res = func(17) print(res) # ### 三元(目)运算符 """ 语法: 真值 if 条件表达式 else 假值 如果条件表达式为真,返回真值,否则返回假值 """ n = 16 res = "偶数" if n % 2 == 0 else "奇数" print(res)
4、小练习:传递两个数, 返回较大的那一个
def func(x,y): if x>y: return x else: return y func = lambda x,y : x if x>y else y res = func(200,100) print(res)
六、练习
#下面代码成立么?如果不成立为什么报错?怎么解决? #1 # a = 2 # def wrapper(): # print(a) # wrapper() #2 # a = 2 # def wrapper(): # a += 1 # print(a) # wrapper() #3 # a = 2 # def wrapper(): # global a # a += 1 # print(a) # wrapper() #4 # def wrapper(): # a = 1 # def inner(): # print(a) # inner() # wrapper() #5 # def wrapper(): # a = 1 # def inner(): # a += 1 # print(a) # inner() # wrapper() #6 # def wrapper(): # a = 1 # def inner(): # nonlocal a # a += 1 # print(a) # inner() # wrapper()
# a = 2 # def wrapper(): # print(a) # wrapper() # 成立
# a = 2 # def wrapper(): # a += 1 # print(a) # wrapper() # 不成立 局部变量不能修改全局变量 # 解决: # a = 2 # def wrapper(): # global a # a += 1 # print(a) # wrapper()
# a = 2 # def wrapper(): # global a # a += 1 # print(a) # wrapper() # 成立
# def wrapper(): # a = 1 # def inner(): # print(a) # inner() # wrapper() # 成立
# def wrapper(): # a = 1 # def inner(): # a += 1 # print(a) # inner() # wrapper() # 不成立 # 要通过 nonlocal引入 a # def wrapper(): # a = 1 # def inner(): # nonlocal a # a += 1 # print(a) # inner() # wrapper()
def wrapper(): a = 1 def inner(): nonlocal a a += 1 print(a) inner() wrapper() # 成立