python10(闭包 装饰器)

📅 发布时间:2026/7/30 10:43:38
python10(闭包  装饰器) 引言好的我们今天继续学习闭包 装饰器在 Python 语言的高级特性中闭包与装饰器是函数式编程范式的两项核心机制。二者在底层逻辑上具有内在一致性闭包提供了函数对其定义时所在作用域中变量的持久访问能力而装饰器则基于闭包机制实现对现有函数行为的无侵入式增强。掌握闭包是理解装饰器的基础二者构成递进关系。一、闭包函数的持久化状态载体闭包的本质可定义为一个内部函数连同其引用的外部函数作用域中的变量共同构成的可调用对象。外部函数执行完毕后其局部变量并不会被立即回收而是通过内部函数的__closure__属性得以保留供后续调用使用。1. 闭包形成的三个必要条件存在函数嵌套定义外部函数内部定义内部函数内部函数引用了外部函数作用域中的变量包括参数外部函数将内部函数作为返回值返回。defouter(a):b5definner():c7print(abc)# 引用了外部变量 a 和 breturninner inner_funcouter(3)# inner_func 为闭包实例inner_func()# 输出 152. 闭包的状态保持机制普通函数执行完毕后其局部变量即被销毁但闭包将所引用的外部变量存储于__closure__元组中每个cell对象保存一个变量的值。print(inner_func.__closure__)# 返回 cell 对象元组print(inner_func.__closure__[0].cell_contents)# 输出 3变量 aprint(inner_func.__closure__[1].cell_contents)# 输出 5变量 b注所有自定义函数均具有__closure__属性非闭包函数该属性为None。该属性主要用于调试与内省一般开发中不直接操作。3. 闭包中的延迟绑定陷阱以下代码输出结果与直觉可能不符defouter():funcs[]forkinrange(3):definner():returnk*k funcs.append(inner)returnfuncs f1,f2,f3outer()print(f1())# 输出 4而非 0print(f2())# 输出 4print(f3())# 输出 4原因分析三个内部函数共享同一变量k循环结束后k的值为 2因此三个函数均返回 4。解决方案利用默认参数在定义时绑定当前值。defouter():funcs[]forkinrange(3):definner(kk):# 默认参数固化 k 的当前值returnk*k funcs.append(inner)returnfuncs# 此时 f1()0, f2()1, f3()4二、装饰器函数行为的修饰与增强装饰器是一种可调用对象函数或类其输入为一个函数输出为一个新的函数。装饰器在不修改原函数源代码的前提下为其附加额外逻辑如日志、计时、权限校验等体现了面向切面编程AOP的思想。使用装饰器的优势提升代码的模块化与可维护性实现关注点分离增强代码复用性同一装饰器可应用于多个目标函数语法简洁提高可读性。1. 无参数的函数装饰器基础实现形式如下importtimedeftimer(func):defwrapper(sleep_time):t1time.time()func(sleep_time)t2time.time()print(fExecution time:{t2-t1}seconds)returnwrappertimer# 等价于 function timer(function)deffunction(sleep_time):time.sleep(sleep_time)function(3)# 实际执行 wrapper(3)执行流程timer语法糖在定义时即执行将function作为参数传入timer返回wrapper并将名称function重新绑定至wrapper。因此调用function(3)时实际执行的是wrapper(3)。2. 带参数的函数装饰器若装饰器本身需接收参数则需构造三层嵌套函数importtimedefinteraction(name):# 第一层接收装饰器参数defwrapper(func):# 第二层接收被装饰函数defdeco(work_time):# 第三层接收原函数参数print(f{name}请将待洗衣物放入。)func(work_time)print(f{name}洗涤完成请取回。)returndecoreturnwrapperinteraction(张三)# 先执行 interaction(张三) 返回 wrapper再 wrapperdefwasher(work_time):time.sleep(work_time)print(设备运行中...)washer(3)执行顺序interaction(张三)先调用interaction(张三)获得wrapper再执行wrapper即washer wrapper(washer)最终washer指向deco。3. 无参数的类装饰器利用类实现装饰器时需在__init__中接收被装饰函数在__call__中定义调用逻辑。importtimeclassTimer:def__init__(self,func):self.funcfuncdef__call__(self,sleep_time):t1time.time()self.func(sleep_time)t2time.time()print(fExecution time:{t2-t1}seconds)Timer# 等价于 function Timer(function)deffunction(sleep_time):time.sleep(sleep_time)function(3)# 调用 Timer 实例的 __call__ 方法4. 带参数的类装饰器带参数时__init__接收装饰器参数__call__接收被装饰函数并返回内部包装函数。importtimeclassInteraction:def__init__(self,name):# 接收装饰器参数self.namenamedef__call__(self,func):# 接收被装饰函数defdeco(work_time):print(f{self.name}请将待洗衣物放入。)func(work_time)print(f{self.name}洗涤完成请取回。)returndecoInteraction(张三)# 实例化 Interaction(张三)再调用 __call__(washer)defwasher(work_time):time.sleep(work_time)print(设备运行中...)washer(3)三、多个装饰器的叠加顺序一个函数可同时应用多个装饰器其执行顺序遵循自下而上的规则即离被装饰函数最近的装饰器先执行。importtimedefdeco(func):defwrapper1(*args):resfunc(*args)returnresreturnwrapper1deftimer(func):defwrapper2(*args):start_timetime.time()resfunc(*args)end_timetime.time()print(fFunction execution time:{end_time-start_time})returnresreturnwrapper2decotimerdefadd(*args):time.sleep(2)returnsum(args)print(add(3,4,5))# 先由 timer 包装再由 deco 包装执行顺序解析定义add后首先执行add timer(add)得到wrapper2然后执行add deco(wrapper2)得到wrapper1。调用时先进入wrapper1其内部调用wrapper2最后才执行原始add函数。四、内置装饰器标准库提供的常见装饰器Python 内置了三个用于类方法的装饰器分别服务于不同场景装饰器功能描述典型用途classmethod定义类方法第一个参数为类对象cls可通过类或实例调用操作类属性或工厂方法staticmethod定义静态方法无需self或cls参数逻辑上属于类但独立于实例工具函数与类相关但不依赖实例状态property将方法转换为只读属性调用时无需括号封装属性访问实现计算属性或权限控制property示例classStudent:def__init__(self,name,age):self.namename self.ageagepropertydefadult_age_p(self):return18defadult_age(self):return18propertydefadult_flag(self):returnself.ageself.adult_age_p stuStudent(张三,18)print(stu.adult_age())# 常规方法调用 → 18print(stu.adult_age_p)# 属性访问 → 18print(stu.adult_flag)# Truestu.age17print(stu.adult_flag)# False# stu.adult_age_p 19 # 赋值操作将抛出 AttributeError因为该属性只读P.S.property可与方法名.setter配合使用实现可写属性本文不作展开。结语闭包与装饰器是 Python 中实现高阶函数与代码增强的重要工具。闭包的核心价值在于维持函数的状态上下文而装饰器则在此基础上提供了灵活的行为注入能力。理解二者的底层实现机制——尤其是函数嵌套、变量绑定与函数对象传递——是掌握 Python 函数式编程的关键一步。建议通过编写计时、日志、权限校验等常见装饰器加深对执行流程与控制权的理解。那么我们今天就到这儿了感谢各位阅读。如有疑问欢迎进一步探讨。下图为本文知识点的思维导图示意