闭包-装饰器
一、闭包
全局变量有被篡改的风险,闭包的形式为函数的嵌套,突破了函数只能用内部变量的限制
既能访问外部变量,又能保证数据安全
闭包
定义双层嵌套函数,内层函数可以访问外层函数的变量;将内层函数作为外层函数的返回,此内层函数就是闭包函数吗,这种现象为闭包现象
即:里面访问外面
def outer(logo):
def inner(msg):
print(f"{logo} {msg}")
# 返回inner函数
return inner
fn1 = outer("python")
fn1("666")
fn2 = outer("C++")
fn2("NB")
outer("python")("1")
闭包中修改外部函数的值,在内部函数中对外部函数变量加上nonlocal
内部函数依赖的外部变量本质上是外部函数的内部临时变量
def outer(num1):
def inner(num2):
nonlocal num1
num1 += num2
print(num1)
return inner
fn = outer(10)
fn(10) # 20
fn(20) # 40
fn(10) # 50
闭包的优点:
1.无需定义全局变量即可实现通过函数,持续访问、修改某个值
2.闭包使用的变量的作用域在函数内,难以被错误地调用修改
闭包的缺点:
由于内部函数储蓄引用外部函数的值,会导致该部分空间一直不被释放
def account_create(initial_amount=0):
def atm(num, deposit=True):
nonlocal initial_amount
if deposit:
initial_amount += num
print(f"存款:+{num},账户余额:{initial_amount}")
else:
initial_amount -= num
print(f"取款:-{num},账户余额:{initial_amount}")
return atm
atm = account_create()
atm(100) # 存款:+100,账户余额:100
atm(200) # 存款:+200,账户余额:300
atm(100, deposit=False) # 取款:-100,账户余额:200
二、装饰器
本质上是闭包,能在不破坏目标函数原有代码和功能的前提下,为目标函数增加新功能
创建一个闭包函数,在闭包函数内部调用目标函数
def sleep():
import random
import time
print("睡眠中......")
time.sleep(random.randint(1, 5))
'''在原代码的基础上增加功能,在sleep前打印我要睡觉了,sleep之后打印我起床了'''
def outer(func):
def inner():
print("我睡觉了")
func()
print("我起床了")
return inner
fn = outer(sleep)
fn()
@装饰器
def outer(func):
def inner():
print("我睡觉了")
func()
print("我起床了")
return inner
@outer
def sleep():
import random
import time
print("睡眠中......")
time.sleep(random.randint(1, 5))
sleep()