闭包函数
互相嵌套的两个函数,如果内函数使用了外函数的局部变量
并且外函数把内函数返回出来的过程,叫做闭包
里面的内函数叫做闭包函数
是不是闭包?
1.内函数用了外函数的那个局部变量
2.外函数返回内函数
1.基本语法形式
def zhaoshenyang_family(): father = "马云" def hobby(): print("我对钱没有一丝丝的兴趣,我不看重钱,这是我爸爸{}说的".format(father)) return hobby func = zhaoshenyang_family() func() print("<==1==>")
判断闭包:
tup = func.__closure__ #返回元祖对象 print(tup[0].cell_contents) # 马云 print(tup)
2.闭包的复杂形式
def zhaowanli_family(): gege = "王思聪" didi = "鞋王,高振宁" money = 1000 def gege_hobby(): nonlocal money money -= 500 print("我交朋友不在乎他有没有钱,反正都没有我有钱.我就喜欢交女朋友... 钱物还剩下{}".format(money)) def didi_hobby(): nonlocal money money -= 400 print("家里有鞋柜,各式各样的奢侈鞋,一双大概20~30万,钱物还剩下{}".format(money)) def big_master(): return [gege_hobby,didi_hobby] return big_master func = zhaowanli_family() print(func) lst = func() print(lst) # 获取哥哥函数 gege = lst[0] gege() # 获取弟弟函数 didi = lst[1] didi()
首先,big_master是闭包函数,然而,gege_hobby和didi_hobby 是通过big_master间接返回出去的,所以它们俩也是闭包函数
3.使用 closure , cell_contents 判定闭包
通过返回的函数.__closure__返回的元祖中有值,就是个闭包,如下图
“”“如果返回的元组中有数据说明是闭包,谁的生命周期被延长就打印谁”“”
tup = func.__closure__ print(tup)
接着往下探索,gege_hobby是闭包函数,里面有两个变量被调用,gege和money。谁的生命周期被延长,元祖中放的是谁。如果变量被修改,打印出来是修改后的内容
#先获取第一个单元格 cell_contents获取对象中的内容
func1 = tup[0].cell_contents
cell_contents获取对象中的内容,获取到didi_hobby函数对象
可以直接调用didi_hobby这个函数
如果不是闭包函数:分两种
1.没有返回内部函数,打印func.__closure__ 报错
2.内部函数没使用外部函数的变量,打印出None
正常的闭包函数打印
print("<11111>") """打印闭包函数didi_hobby中,生命周期被延长的属性""" print(func1.__closure__[0].cell_contents) func1() # 在获取第二个单元格 cell_contents获取对象中的内容 func2 = tup[1].cell_contents print("<22222>") """打印闭包函数gege_hobby中,生命周期被延长的属性""" print(func2.__closure__[0].cell_contents) func2()
闭包特点
特点:在闭包函数中,内函数使用了外函数的局部变量,
该变量会与内函数发生绑定,延长该变量的生命周期,
持续到脚本执行结束.
def outer(val): def inner(num): return val + num return inner func = outer(10) res = func(15) print(res)
闭包的意义
全局变量的作用域大,容易被篡改
num = 0 def click_num(): global num num += 1 # num = num + 1 print(num) click_num() click_num() click_num() num = 100 click_num() click_num()
全局变量一直在被修改
#改造,用闭包来实现
“”"
闭包的意义:
闭包可以优先使用外函数中的变量, 并对闭包中的值起到了封装保护的作用. 外部无法访问.
“”"
def outer(): x = 0 def click_num(): nonlocal x x += 1 print(x) return click_num click_num = outer() click_num() click_num() click_num() x = 100 click_num() click_num()
这样,即使修改全局变量,也不影响局部变量的值,局部变量被保护起来。每次执行是根据局部变量的变量值来进行运算