文章目录
闭包函数
什么是闭包
关于闭包,即函数定义和函数表达式位于另一个函数的函数体内(嵌套函数)。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。也就是说,内部函数会在外部函数返回后被执行。而当这个内部函数执行时,它仍然必需访问其外部函数的局部变量、参数以及其他内部函数。这些局部变量、参数和函数声明(最初时)的值是外部函数返回时的值,但也会受到内部函数的影响。
例如:
def outer():
name = '隔壁老王'
def inner():
print("在inner里打印外层函数的变量",name)
return inner # 注意这里只是返回inner的内存地址,并未执行
f = outer() # .inner at 0x1027621e0>
f() # 相当于执行的是inner()
注意此时outer已经执行完毕,正常情况下outer里的内存都已经释放了,但此时由于闭包的存在,我们却还可以调用inner, 并且inner内部还调用了上一层outer里的name变量。这种粘粘糊糊的现象就是闭包。
闭包的意义
返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
闭包的定义:
如果内函数使用了外函数的局部变量
并且外函数把内函数返回出来的过程 叫做闭包
里面的内函数是闭包函数
复杂的闭包函数(多层)
def mashengping_family():
father = "马云"
jiejie = "马蓉"
meimei = "马诺"
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) # <function mashengping_family.<locals>.big_master at 0x000001F4CB0F5620>
# 返回的是元组
tup = func()
print(tup) # (<function mashengping_family.<locals>.jiejie at 0x0000013D5B175158>, <function mashengping_family.<locals>.meimei at 0x0000013D5B175268>)
# 获取姐姐
jiejie = tup[0]
# 获取妹妹
meimei = tup[1]
# big_master 是闭包函数,是直接被mashengping_family返回出来的
# jiejie,meimei 是通过big_master间接被返回到函数外面的
# 调用妹妹
meimei() # 还剩下800元
# 调用姐姐
jiejie() # 还剩下100元
# 获取闭包函数所使用的变量 __closure__
res = func.__closure__
print(res) # (<cell at 0x000001AF2B5A76A8: function object at 0x000001AF2B645158>, <cell at 0x000001AF2B5A76D8: function object at 0x000001AF2B645268>)
# cell_contents 用来获取单元格对象当中的闭包函数
jiejie = res[0].cell_contents # <function mashengping_family.<locals>.jiejie at 0x0000019161005158>
meimei = res[1].cell_contents # <function mashengping_family.<locals>.meimei at 0x0000019161005268>
i = jiejie.__closure__[0] # <cell at 0x0000020E9B977708: int object at 0x0000000054928CD0>
j = meimei.__closure__[0] # <cell at 0x0000020E9B977708: int object at 0x0000000054928CD0>
a = jiejie.__closure__[0].cell_contents # 100
b = meimei.__closure__[0].cell_contents # 100
闭包的特征
概念:
内函数使用了外函数的局部变量
那么该变量与闭包函数发生绑定
延长该变量的生命周期
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) # 25
"""
10=实参-->val形参
因为内函数inner是闭包函数 使用了外函数val
那么该变量val生命周期被延长 没有随着函数调用的结束而释放
res = inner(15) => return val+num =>10+15 =>25
"""
闭包的意义
闭包可以优先使用外函数中的变量,并对闭包中的值起到了封装保护的作用,外部无法访问
# 模拟鼠标点击次数
num = 0
def click_num():
global num
num += 1
print(num)
click_num() # 1
click_num() # 2
click_num() # 3
num = 100
click_num() # 101
click_num() # 102
'''
很显然,这样是不行的,定义了全局变量100后,值就从100开始加了.
想一个办法,让其就算在中间插入num=100也没用
'''
# 解决方案
def click_num():
num=0
def func():
nonlocal num
num+=1
print(num)
return func
func = click_num()
func() # 1
func() # 2
num = 1000
func() # 3
func() # 4
func() # 5
匿名函数(lambda)
用一句话来表达只有返回值的函数
语法:lambda 参数 : 返回值
目的追求代码:简洁,高效
无参的lambda 表达式
# 无参的lambda 表达式
def func():
return "123"
# 改写
func = lambda : "123"
res = func()
print(res)
有参的lambda 表达式
# 有参的lambda 表达式
def func(n):
return type(n)
# 改写
func = lambda n : type(n)
print( func([1,2,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)
嵌套函数的lambda表达式
#============ 函数嵌套 ================
#函数内包含函数
def fun1(a):
def funa(a):
return a **2
def funb(a):
return a **3
return funa(a) + funb(a)
print('函数嵌套:{}:'.format(fun1(3)))
#============ lambda表达式代替嵌套函数 ==============
#lambda表达式替代嵌套函数
def fun2(a):
f1 = lambda a : a ** 2
f2 = lambda a : a ** 3
return f1(a) + f2(a)
result = fun2(3)
print('lambda表达式代替函数嵌套: {}'.format(result))
三元运算符(三目运算符)
"""
语法:
真值 if 条件表达式 else 假值 如果条件表达式为真,返回真值,否则返回假值
"""
n = 16
res = "偶数" if n % 2 == 0 else "奇数"
print(res)