Python 九阳神功之叁:闭包与装饰器 · 借力打力 第 3 篇 · 口诀心法闭包与装饰器 · 借力打力闭包如内力绵延不绝装饰器如太极推手——不改变招式却能化腐朽为神奇。本篇传授 Python 高阶编程的「借力打力」之术让你写出更优雅、更强大的代码。Python 高阶编程闭包与装饰器1. 全局变量与 global 关键字global关键字用于在函数内部声明使用全局变量从而对全局变量进行修改。base0defsum_add(num):globalbase basenumprint(base)sum_add(10)# 输出: 10sum_add(10)# 输出: 20sum_add(10)# 输出: 30警告绝对不推荐使用global应该在函数内部解决自己的业务问题这个方案应该被 pass。2. 闭包Closure2.1 什么是闭包来源定义官方定义内部函数引用外部函数的变量rucy定义让本该被垃圾回收的变量永远留在内存中为内部函数所用2.2 闭包的形成条件有函数嵌套外部函数内定义内部函数外部函数返回内部函数名内部函数引用外部函数的变量使用nonlocal关键字声明变量表示向上查找而非当前作用域的局部变量2.3 闭包基本示例deffun_outer():num0deffun_inner():nonlocalnum num10returnnumreturnfun_inner ffun_outer()print(f())# 输出: 10print(f())# 输出: 20print(f())# 输出: 302.4 手动释放闭包delf# 删除函数引用fNone# 或置为 None触发垃圾回收3. 函数柯里化面试高频题阿里面试题实现一个add函数支持链式调用add(1) → 1 add(1)(2) → 3 add(1)(2)(3) → 6 add(1)(2)(3)(10) → 16实现代码defadd_fun(num):num_list[num]definner_add(valNone):ifvalisNone:returnsum(num_list)num_list.append(val)returninner_addreturninner_add# 测试print(add_fun(1)(2)(3)(4)(5)(6)(1000)(1000)(100)(2000)())4. 装饰器Decorator4.1 装饰器原理装饰器本质上就是一个闭包函数满足以下条件有函数嵌套有返回内部函数有函数引用增加额外的功能4.2 装饰器执行流程图解原始函数: publish_comment() ↓ 被装饰器 check_login 修饰 ↓ 执行流程: 1. 检查登录状态新增功能 2. 执行原 publish_comment()原有功能 3. 返回结果4.3 无参无返回值的装饰器defcheck_login(fn):definner():accountinput(请输入您的账号:)passwordinput(请输入您的密码:)ifaccountadminandpassword123456:fn()else:print(用户名或者密码错误)returninnercheck_logindefpublish_comment():print(发表评论)publish_comment()# 先检查登录再发表评论4.4 带参数、带返回值的装饰器通配写法使用*args和**kwargs通配所有参数deflog(fn):definner(*args,**kwargs):print(开始执行某函数)resfn(*args,**kwargs)print(某函数执行完毕)returnresreturninnerlogdefsum_add(a,b):returnablogdefcalc_all(*args,**kwargs):returnsum(args)sum(kwargs.values())print(sum_add(1,2))# 输出: 3print(calc_all(1,2,3,age18))# 输出: 244.5 语法糖写法对比传统写法语法糖写法f log(common)logf()def common(): passcommon()# 语法糖写法logdefcommon():passcommon()# 直接调用自动拥有 log 的功能4.6 wraps 保留元信息被装饰后原函数的__name__、__doc__等信息会丢失使用wraps可以保留fromfunctoolsimportwrapsdefcheck_code(fn):wraps(fn)# 保留 fn 的元信息definner(*args,**kwargs):codeinput(请输入验证码:)ifcode1234:returnfn(*args,**kwargs)else:print(验证码错误)returninnercheck_codedeflogin():用户登录函数print(用户开始登录)print(login.__name__)# 输出: login不加 wraps 会输出 innerprint(login.__doc__)# 输出: 用户登录函数4.7 多个装饰器叠加使用执行顺序从下往上靠近函数的先执行log# 第三步日志记录check_user# 第二步检查用户名check_code# 第一步检查验证码defpublish(user_name,content):print(f{user_name}:发表内容:{content})完整示例fromfunctoolsimportwrapsdeflog(fn):wraps(fn)definner(*args,**kwargs):print(f{fn.__name__}:开始执行)resfn(*args,**kwargs)print(f{fn.__name__}:执行完毕)returnresreturninnerdefcheck_user(fn):wraps(fn)definner(*args,**kwargs):user_nameinput(请输入您的用户名:)ifuser_nameadmin:returnfn(*args,**kwargs)print(用户名错误)returninnerdefcheck_code(fn):wraps(fn)definner(*args,**kwargs):codeinput(请输入验证码:)ifcode1234:returnfn(*args,**kwargs)print(验证码错误)returninnerlogcheck_usercheck_codedefpublish(user_name,content):print(f{user_name}:发表内容:{content})publish(rucy,AI时代人人可编程)4.8 带参数的装饰器当装饰器本身需要接收参数时需要三层嵌套importtimedefcheck_time_out(msFalse):defcheck_time(fn):definner(*args,**kwargs):beginint(time.time())resfn(*args,**kwargs)endint(time.time())ifmsisTrue:print(f耗时:{(end-begin)*1000}ms)else:print(f耗时:{end-begin}s)returnresreturninnerreturncheck_timecheck_time_out(msTrue)# 传入参数以毫秒为单位defbig_loop():foriinrange(5000000):pass# 模拟耗时操作big_loop()带参数装饰器结构模板def outer_fun(装饰器参数): def inner_fun(fn): def inner(*args, **kwargs): # 在函数执行前后添加额外功能 return fn(*args, **kwargs) return inner return inner_fun5. 快速记忆表知识点关键点应用场景global函数内修改全局变量❌ 不推荐使用nonlocal闭包内修改外部函数变量闭包中使用闭包内部函数 外部变量 nonlocal数据持久化、计数器wraps保留原函数元信息装饰器开发装饰器闭包 函数引用 额外功能日志、权限验证、计时多个装饰器从下往上执行组合多个增强功能带参装饰器三层嵌套配置化装饰器6. 核心公式必背闭包公式外部函数(有变量) → 内部函数(引用变量 nonlocal) → 返回内部函数装饰器公式def 装饰器名(fn): def inner(*args, **kwargs): # 前置操作新增功能 res fn(*args, **kwargs) # 后置操作新增功能 return res return inner 装饰器名 def 原函数(): pass带参装饰器公式def 外层(参数): def 中层(fn): def inner(*args, **kwargs): return fn(*args, **kwargs) return inner return 中层

相关新闻

最新新闻

Agent范式在分布式系统与快手面试中的应用解析

Agent范式在分布式系统与快手面试中的应用解析

1. Agent范式在快手面试中的核心考察点快手作为国内领先的短视频平台,其技术面试向来以紧跟行业趋势著称。当面试官抛出"Agent范式"这个题目时,他们真正想考察的是候选人对现代分布式系统设计理念的掌握程度。我在参与多次技术评审后发现&…

2026/8/24 5:32:34
从特斯拉Optimus看人形机器人核心技术栈与工程化挑战

从特斯拉Optimus看人形机器人核心技术栈与工程化挑战

在机器人技术和人工智能领域,特斯拉的Optimus项目一直备受瞩目。它不仅仅是一个仿人形机器人,更代表了通用人工智能(AGI)与物理世界交互的终极载体之一。近期,关于其将“消除贫困”和“超越人类外科医生”的愿景引发了…

2026/8/24 5:32:34
Java开发者必知的AI面试题与实战技巧

Java开发者必知的AI面试题与实战技巧

1. Java面试中的AI热点:为什么这十个问题必问?2023年起,AI技术对Java开发岗位的要求产生了显著影响。根据主流招聘平台数据,85%的中高级Java岗位JD中明确要求候选人具备AI集成或机器学习基础能力。这十个高频问题之所以成为面试官…

2026/8/24 5:32:34
Java并发锁实战:synchronized、ReentrantLock与读写锁核心解析

Java并发锁实战:synchronized、ReentrantLock与读写锁核心解析

1. 项目概述:深入Java并发锁的实战核心在Java后端开发和高并发场景里,锁是绕不开的核心话题。无论是处理电商秒杀时的库存扣减,还是管理多用户同时编辑的配置中心,我们都需要一种机制来保证数据在并发访问下的正确性。很多开发者&…

2026/8/24 5:32:34
Windows深度学习环境稳定性黄金法则:CPU/GPU分层配置与四重校验

Windows深度学习环境稳定性黄金法则:CPU/GPU分层配置与四重校验

1. 这不是教程,是我在Windows上踩了三年坑后整理的深度学习环境配置实录 你搜“Windows 深度学习环境配置”,页面里全是复制粘贴的命令堆砌、版本号罗列、截图拼接——看着步骤完整,一上手就报错:CUDA版本不匹配、PyTorch安装后 …

2026/8/24 5:32:34
Vue项目部署实战:使用宝塔面板从零到一上线静态应用

Vue项目部署实战:使用宝塔面板从零到一上线静态应用

1. 项目概述:从本地开发到线上服务的最后一公里 每次在本地把Vue项目跑得顺风顺水,看着控制台一片绿色,页面交互丝滑流畅,心里总会涌起一股成就感。但这份成就感,只有当你成功地把项目部署到一台真正的服务器上&#x…

2026/8/24 5:27:33