在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称为闭包。
内部函数使用外部变量
def outer(name):
def inner(name1):
print(f"<{name}><{name1}><{name}>")
return inner
f1 = outer("wyx")
f1("sxx")
f2 = outer("sx")
f2("wyx")
<wyx><sxx><wyx>
<sx><wyx><sx>
如果需要修改外部函数变量的值,需要使用nonlocal关键字修饰外部函数的变量才可以在内部函数中修改它。
def outer(num1):
def inner(num2):
nonlocal num1
num1 += num2
print(num1)
return inner
fn = outer(10)
fn(10) #20
fn(10) #30
account = 0
def atm(num, deposit=True):
global account
if deposit:
account += num
print(f"存款+{num},余额{account}")
else:
account -= num
print(f"取款-{num},余额{account}")
atm(300)
atm(100, False)
存款+300,余额300
取款-100,余额200
#使用闭包实现
def account(amount=0):
def atm(num, deposit=True):
nonlocal amount
if deposit:
amount += num
print(f"存款+{num},余额{amount}")
else:
amount -= num
print(f"取款-{num},余额{amount}")
return atm
atm = account()
atm(100)
atm(200)
存款+100,余额100
存款+200,余额300
优点,使用闭包可以让我们得到:
无需定义全局变量即可实现通过函数,持续的访问,修改某个值
闭包使用的变量的所用于在函数内,难以被错误的调用修改
缺点:
由于内部函数持续引用外部函数的值,所以会导致这一部分内存空间不被释放,一直占用内存
装饰器其实也是一种闭包,其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能。
def outer(func):
def inner():
print("我要睡觉了")
func()
print("我要起床了")
return inner
def sleep():
import random
import time
print("睡眠中。。")
time.sleep(random.randint(1,4))
fn = outer(sleep)
fn()
我要睡觉了
睡眠中。。
我要起床了
使用@outer定义在目标函数sleep之上
def outer(func):
def inner():
print("我要睡觉了")
func()
print("我要起床了")
return inner
@outer
def sleep():
import random
import time
print("睡眠中。。")
time.sleep(random.randint(1,4))
sleep()