Python闭包与装饰器:代码封装的魔法

📅 2026/6/28 19:25:54
Python闭包与装饰器:代码封装的魔法
1.闭包在函数中,函数结束后,函数内定义的变量就销毁了,但有时需要保存函数内的变量,并在此变量基础上再完成一系列操作(相当于延长函数内变量的生命周期)而使用外部函数变量的内部函数就称之为闭包闭包可以保存函数内的变量,使得变量不会随着调用函数而被销毁在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数构造条件:1.有函数嵌套2.内部函数引用外部函数参数3.外部函数返回内部函数名#外部函数Def 外部函数名(外部参数):#内部函数Def 内部函数(内部参数):使用外部函数的参数return 内部函数名函数名和函数名()是两个概念,前者表示函数对象 后者表示调用函数 获取返回值例如:def add(num1:int): def wrapper(num2:int): return num1num2 return wrapper f add(3) # add(3) 调用函数对象add 传入参数num1 3 同时返回了 wrapper # 用f 接收了 wrapper 这个函数对象 print(f) # 所以单独打印f的结果为 function add.locals.wrapper at 0x000001A6A305B320 表示一个对象函数 对象名 为 wrapper # 此时f wrapper # f(2) wrapper(2) print(f(2)) # - 等同于 wrapper(2) # 而调用wrapper(2) 执行 num1num2 - 32 结果为5如果整体写 f add(3)(2) 输入结果也是5,逐步拆解跟上面是一样的在内存地址的角度思考:有两个函数add(num1) 假如地址值为 0x001 和 函数wrapper(num2) 假如地址值为 0x002而 f add(3) 调用add函数 返回了wrapper结果为 f wrapper f指向了 wrapper的地址0x0022.装饰器作用:不修改原来函数代码的基础上,对该函数的功能进行扩展(扩展有限,只对函数开始之前和结束之后进行扩展)应用场景:1. 打印日志信息(例如:包含调用函数的函数名,传递了哪些参数,调用时间,运行时间等)2. 权限控制: 例如用户登录,判断用户拥有哪些权限3.缓存2.1 自定义装饰器构造条件:1.有函数嵌套2.内部函数引用外部函数参数3.外部函数返回内部函数名4.有额外功能装饰器就是对闭包的升级例如:def decorate(func): def wrapper(*args,**kwargs): print(计算开始...) func() print(计算结束) return wrapper def add(): print(f10 20 { 10 20}) add_wrapper decorate(add) add_wrapper() # 没有改变add 原函数 但是对add增加了一些东西输出结果为:计算开始...10 20 30计算结束语法糖写法:在要修饰的函数上 添加 装饰器名称装饰器名称就是 decorate [自定义装饰器的最外部函数名]def decorate(func): def wrapper(*args,**kwargs): print(计算开始...) func() print(计算结束) return wrapper decorate def add(): print(f10 20 { 10 20}) add() # 调用add函数输出结果:计算开始...10 20 30计算结束可能单个函数看上去觉得这样写小题大做了但是如果你有很多计算一类的函数 ,都想在函数执行之前输出计算开始 和 函数结束后输出 计算 结束,就要一个个添加, 但写个装饰器 就不用重复写了2.2 有参无返回值上面2.1中的介绍都是无参无返回值的写法# 定义装饰函数 def decorate(func): # 定义内部函数 def mrapper(num1, num2): # 添加新功能 print(f正在计算...) # 调用外部餐宿 func(num1, num2) # 返回内部函数 return mrapper # 定义被装饰函数 decorate def sum2(num1, num2): print(fnum1 num2 {num1 num2}) num1 int(input(请输入被加数)) num2 int(input(请输入被数)) # 测试 sum2(num1, num2)2.3 无参有返回值的函数#定义装饰函数 def decorate(func): # 定义内部函数实现函数嵌套 def inner(): # 有新增功能 print(正在计算....) # 调用外部参数 return func() # 返回内部函数 return inner #定义被装饰函数 decorate def sum3(): a 10 b 20 return a b # 测试 sum3 sum3() print(sum3)2.4 有参有返回值的函数# 定义装饰函数 def decorate(func): # 定义内部函数 有嵌套函数 def marpper(num1,num2): # 有参数 # 新增功能 print(正在计算) #调用外部函数 return func(num1,num2) # 且有返回值 # 返回内部函数 return marpper # 定义被装饰函数 # decorate def sum4(num1, num2): # 有参数有返回值 return num1 num2 sum4 sum4(5,1) print(sum4) # 传统方式 sum4 decorate(sum4) sum sum4(5,1) print(sum)2.5 可变参数函数def decorate(func): def mapper(*args, **kwargs): print(正在努力计算....) return func(*args, **kwargs) return mapper #定义原函数 decorate def get_sum(*args,**kwargs): return sum(args) sum(kwargs.values()) sum get_sum(1,2,3,4,a 5,b 6) print(sum)我认识的一位著名的名人说过,如果不理解没关系,记公式不管有没有参数,就记可变参数函数这个样子,记住了多用就理解了2.6 多个装饰器装饰一个函数多个装饰器装饰一个函数时,是按照由内而外的顺序装饰的但如果使用装饰器来写,看到的效果是从上往下执行# 多个装饰器装饰同一个函数 def check_login(func): def inner(): print(请先登录) func() return inner def check_code(func): def inner(): print(校验成功) func() return inner check_login # 从上往下执行 check_code # 从上往下执行 def comment(): print(发表评论) comment() # 传统方式 comment check_code(comment) # 由内而外 comment check_login(comment) # 由内而外 comment()2.7 带参数的装饰器使用带有参数的装饰器,其实就是在装饰器外面又包裹了一个函数,使用该函数接受参数,返回装饰器一个装饰器的参数只能有一个,如果装饰器有多个参数,可以在改装饰器的外边再包裹一层,把该装饰器当作内部函数返回即可# 定义一个既能装饰减法,又能装饰减法的装饰器 # 定义装饰函数 def loging(flag): def decorate(func): # 定义内部函数 1.有函数嵌套 def wrapper(num1,num2): if flag : print(正在努力进行加法运算中) elif flag -: print(正在努力进行减法运算中) return func(num1,num2) return wrapper return decorate #定义原函数减法 loging(-) def reduce(num1,num2): return num1-num2 # 定义原函数加法 loging() def sum(num1,num2): return num1num2 # 测试 reduece reduce(10,5) print(reduece) sum sum(10,5) print(sum)个人理解就这么点,没有画图如果有画图指向的话 执行流程会更好