ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

深入浅出Python闭包与装饰器:原理与基础用法

深入浅出Python闭包与装饰器:原理与基础用法 你可曾有过好奇, , 那当中优雅的语法背后隐匿着怎样的逻辑要是你运用timer去装饰函数就能够自动进行运行时间统计, 借由便能轻而实施权限校验之际, 实际上都是闭包以及装饰器在悄然运作了这俩看起来抽象的概念, 正是代码简洁与灵活的秘密武器今儿个, 我们要从原理一直到实践, 一步步去揭开它们的面纱了。1. 闭包函数里的状态容器1.1 闭包的定义与形成条件闭包属于函数式编程里的核心特性, 归根结底是“嵌套函数、自由变量以及作用域延伸”组成的结合体。一旦内层的函数引用了处于外层函数作用范围里的变量, 并且外层函数将内层函数返回, 如此便形成了闭包。形成闭包必须满足三个条件代码示例最简单的闭包实现def ():# 外层函数变量自由变量info def ():# 内层函数引用外层自由变量print(f接收到消息{info})# 返回内层函数对象不执行10# 创建闭包实例固定自由变量info为Hello 11 (Hello )12# 调用闭包此时外层函数已执行完毕但info仍被保存13() # 输出接收到消息Hello1.2 闭包的工作原理自由变量的保鲜术闭包最为关键的神奇魔力主要在于能够延长自由变量的生命周期, 在正常状况情形下, 当函数执行完毕之后, 其内部所包含的变量会被进行垃圾回收操作, 然而闭包依靠属性, 把自由变量保存于特殊的cell对象里边, 致使内层函数就算脱离了外层函数的作用域范围, 依旧能够访问这些变量。代码示例探索闭包的内部状态def ():count 0 # 自由变量被闭包保存的计数器def ():count # 声明修改外层变量 3特性count 1count# 创建计数器闭包10 ()11print(()) # 输出112通过执行print(())这一操作, 其输出结果为2, 此结果表明count值处于被持续保存的状态。1314# 查看闭包保存的自由变量15print(.) # 输出(,)16进行print(..)操作, 其输出结果为2此数字是通过直接访问cell里的count值得出。1.3 闭包的实用场景简洁的状态管理解决“需要携带状态但不想用类”这一情景状况, 闭包最为擅长, 其常见应用涵盖以下方面:代码示例温度转换器工厂def r(unit):根据单位生成不同的温度转换函数def t(c):c * 1.8 32def (c):c 273.15# 根据外层参数返回不同的内层函数if unit :t10elif unit :111213# 创建不同转换器闭包实例14to_f r()15to_k r()1617打印, 将零进行转换为华氏度的操作之后的结果, 此结果为三十二点零, 也就是零摄氏度所对应的华氏度数值。18打印, 将零摄氏度转换为开尔文的结果, 输出为二百七十三点一五, 即print(to_k(0)) # 输出: 273.150℃转开尔文。2. 装饰器函数的增强插件2.1 装饰器的本质与语法糖闭包的典型应用之中有装饰器, 其本质是这样一种高阶函数, 即接受函数当作参数, 并且返回增强版函数, 借助装饰器名语法糖, 装饰器的使用得以简化, 进而让代码变得更加简洁。核心逻辑是, 等价于func (func), 这意味着, 要将被装饰函数替换成, 装饰器返回的新函数。代码示例无参装饰器基础实现def (func):打印函数调用日志的装饰器def ():print(f 函数 {func.} 开始执行)func() # 调用原函数print(f 函数 {func.} 执行完毕)# 使用语法糖应用装饰器1011def ():12print(Hello !)1314# 调用被装饰后的函数15()16# 输出17# 函数 开始执行18# Hello !19# 函数 执行完毕2.2 基础装饰器的实现步骤实现一个装饰器通常需要3步定义装饰函数接受被装饰函数func作为参数自定义一个用于包装的函数, 在这个函数里面进行对func的调用, 并且添加诸如日志记录、计时操作以及权限校验之类的增强逻辑。返回包装函数将作为结果返回替换原函数。代码示例计时装饰器带参数与返回值处理timedef (func):def (*args, **):包装函数支持任意参数和返回值 time.time()对原函数展开调用, 同时, 将其返回值予以捕获, 具体形式为 func(*args, **)。 time.time()你提供的内容存在错误信息并有缺失部分, 不太能准确按照要求改写。请你检查并修正完整准确的内容后再次提出。10# 返回原函数的结果11121314def (n):15计算1到n的和16sum(range(1, n1))1718# 调用被装饰的函数19print(()) # 输出20于此同时进行打印: 进行执行操作所耗费的时间为: 零点零零二三秒此时间会依据设备不同而有所变化。2.3 进阶技巧带参数的装饰器与装饰器链要是装饰器得自定义参数, 像日志级别、权限角色这类, 那就得用三层嵌套, 外层接收参数, 中层接收函数, 内层是包装函数。而且, 能把多个装饰器叠加一块用, 也就是装饰器链, 执行顺序是从下往上, 靠近函数的装饰器先运行。代码示例1带参数的日志装饰器def (level):带日志级别参数的装饰器三层嵌套def (func):def ():print(f{level.upper()}函数 {func.} 被调用)func()# 应用带参数的装饰器()10def ():11print(执行核心操作...)1213()14# 输出 函数 被调用15# 执行核心操作...代码示例2装饰器链的执行顺序def (func):def ():print(装饰器A开始)func()print(装饰器A结束)def (func):def ():10print(装饰器B开始)11func()12print(装饰器B结束)131415# 装饰器链从下到上执行先B后A161718def ():19print(目标函数执行)2021()22# 输出顺序23# 装饰器A开始24# 装饰器B开始25# 目标函数执行26# 装饰器B结束27# 装饰器A结束3. 总结闭包借助保存自由变量达成“函数带状态”, 这是装饰器的根基所在装饰器是基于闭包的, 它提供了函数增强的一种优雅方案。掌握这两者能够使你编写出更为简洁、极具模块化特点的代码, 无论是从数据封装方面, 还是到日志、缓存、权限控制等领域, 闭包与装饰器都是无处不在的。要记住: 闭包是“状态容器”, 装饰器是“函数插件”, 它们联袂构成函数式编程的核心魅力句号。4. 学习好书推荐能否曾经有过那种, 开始接触时觉得不难入门, 然而却一直处于在“能够看明白”以及“能够书写得好”这两者之间来回犹豫不决的情况呢? 到了现在此时此刻, 应当借助两本堪称经典的作品, 从而彻彻底底地将你的关键脉络給打通。一个不算枯燥语法手册的, 能通过一个个真实项目, 让你从简单数据可视化开始一直到开发小游戏, 在动手乐趣里自然掌握核心概念的心路指南介绍出适合新人告别看了就忘而向真正的理解拥抱前行的《编程从入门到实践》, 是你的完美起点。编程 从入门到实践 第3版图灵出品¥81.7京东月销量100好评率99%无理由退换京东配送购买当你筑牢根基, 《面向对象编程指南》会引领你步入高手之境。面向对象乃是创作出优雅且可复用代码的关键所在, 这本书以深入浅出之态揭示其核心要义。你能够学会怎样构筑更为强大的程序, 为日后投身复杂项目奠定坚实根基。面向对象编程指南(异步图书出品)¥62.3京东好评率99%无理由退换京东配送旗舰店购买这两本书构成了一个堪称完美的成长闭环, 此闭环是从毫无基础起始, 直至成为专业开发者的过程。不管你是身为殷切渴望实现转行的职场之人, 又或者是满心期望提升自身竞争力的在校学生, 这一套组合都能够使你规避步入需耽搁半年时间的偏离正轨之路。
返回列表