Python闭包和装饰器的学习
之前看了不少的帖子,总是看了这篇帖子说的理解了,换篇帖子说的又不理解了,把人弄晕了,究其原因还是因为没有把底层原理理解。
这两个概念总是放在一起说,两者之间肯定是有关系的,那到底什么关系,这两个东西是一样的还是不一样的?感觉大部分帖子都是各解释各的,放一大堆examples,光背概念对我这种底子不好的同学很难理解。
今天刷到B站一个up主(python杂谈)的讲解,解释了很多,感觉自己又懂了😂😂,今天先总结一下,也不知道这次理解的对不对。我在这里对python函数就不做展开了。
引用一下查到的一些解释:
把这个定义拆解一下,我理解闭包有几个特性:
1、在函数内部再定义函数
2、内部函数要引用外部函数的变量
3、外部函数要把内部函数作为返回值
4、通过闭包能把外部函数的变量持久保存
先看一个最简单的例子:定义了一个函数outer(),里面再嵌套定义一个函数inner(),先不管inner函数里面实现了什么,outer函数用inner函数作为它的返回值。
这里要注意写法,返回的inner函数不带括号了。先来定义一个n 引用outer()看看它是什么样的,再 print(n, n.__name__)。
可以看到,因为outer返回值是inner函数,所以n()其实就是调用了inner()。
但是,根据闭包的定义,这好像还不能称为闭包,因为inner没有引用它外面的变量,使用 print(n.__closure__)查看返回None。那变化一下,outer可以带参数,inner也可以带参数,inner里使用outer的参数和变量,outer里也可以使用inner。
这个应该算是闭包了吧?所以闭包是指这个内函数吗?还是内外函数一起组成了闭包?
闭包的样子知道了,那装饰器和它有什么关系呢?先看下面的例子。
先关注这个函数的入参,我们给它传入一个函数看看结果。
先定义一个简单的函数hello,a 引用了上面的waitfor2seconds方法,给它传了函数hello(注意写法不带括号了),返回的是hello本身,所以a是hello了。再调用a的时候其实就是调用hello函数。
可以看到结果,先输出了waitfor2seconds的内容,再输出了hello里的内容。
上面闭包的例子我们了解到,函数可以作为另一个函数的返回值。这个例子我们了解了,函数也可以作为另一个函数的参数,这是理解装饰器的关键点。
现在换一种写法,直接调用hello函数,它得到的结果和上面的写法是一模一样的,这里就是把waitfor2seconds方法作为装饰器放在要装饰的函数前使用了。
@waitfor2seconds 效果等价于 waitfor2seconds(hello)
现在升级一下,让这个装饰器再复杂一些。像闭包一样,我们在函数waitfor1seconds里面再定义一个函数wrapper,并且以wrapper作为它返回值,并在wrapper里调用了它的入参func。
得到的结果流程一致,先执行外部,再执行内部。可以看出,装饰器模式就是在不改变现有功能的代码的基础上,为功能增加额外的行为。
装饰器还有更多的扩展,装饰带有定长参数的函数时内部函数也要带上参数,装饰带有返回值的函数时内部函数也要带上返回值,装饰带不定长参数的函数时内部函数使用*args,**kwargs作为参数,一个函数还可以带多个装饰器。
今天整理这么多,虽然是弄清了闭包和装饰器的结构,但两者的关系也没太理清,下次再写了。
参考:https://www.jianshu.com/p/ee82b941772a
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现