Python闭包:函数嵌套的魔力
概念
官方定义:闭包(Closure) 是 Python 中一种特殊的函数嵌套现象:内层函数引用了外层函数的变量(非全局变量),且外层函数返回了这个内层函数。简单来说,闭包让内层函数 “记住” 了外层函数的变量环境,即使外层函数已经执行完毕,内层函数依然能访问和使用这些变量。
狭隘的理解,闭包就是函数嵌套函数。
但是满足闭包,需满足3个条件(如下图代码)
1.存在函数嵌套
2.内层函数引用外层函数变量(非全局变量)
3.外层函数返回内层函数
def outer():
print('outer...')
x = 10
def inner(): # 1.函数嵌套
print('inner')
return x + 1 # 2.引用外层函数变量
return inner # 3.返回内层函数
a = outer()
print(a())
如上代码,a = outer()执行完返回inner,这里a引用的就是inner,此时打印a,打印的是a的内存地址。
<function outer.<locals>.inner at 0x0000020552E7A290>
a()执行,相当于调用内层函数。
图解

当外层函数执行以后,此时有了内层函数的定义和外层函数的变量a和变量b,这个时候再把内层函数吐出来,注意,吐出来的环境包括内层函数和变量a,并不包含变量b,因为内层函数并没有引用变量b。
可能你想,这么做有什么意义?比如,变量记忆、定制函数。
案例
现有这样的需求,普通用户折扣95折,vip用户折扣8折,买100元商品后,普通用户和vip用户折扣后的金额是多少?
常用的思路:
def funcA(discount, price):
return discount * price
res1 = funcA(0.95, 100)
print(f"普通用户,100元优惠价格是,{res1}")
res2 = funcA(0.8, 100)
print(f"vip用户,100元优惠价格是,{res2}")
调用的时候传discount,本身这样设计没有问题,除了繁琐没毛病(重复传折扣)。那有没有办法,不管是普通用户还是vip用户,调用的时候只要传price就行?
def outer(discount):
def inner(price):
return discount * price
return inner
normal = outer(0.95)
vip = outer(0.8)
print(f"普通用户,100元优惠价格是,{normal(100)}")
print(f"普通用户,100元优惠价格是,{vip(100)}")
很明显,同样的一个规则,衍生出来两个函数。函数normal用于普通用户折扣计算,函数vip用于vip用户折扣计算(定制函数),首次调用后,折扣值(discount)被保存下来(变量记忆)。后续计算只需要传价格即可,代码复用性强。如果折扣变化,修改一处即可,如果是之前的方式,则牵一发而动全身。
PS:如果需要修改外层函数的变量值,需要使用nonlocal,如下图
def outer():
print('outer...')
x = 10
def inner():
print('inner')
nonlocal x
x = x + 1
return x
return inner
更多推荐


所有评论(0)