python装饰器与闭包_我所理解的Python闭包与装饰器

众所周知, 在Python的世界里, 函数是作为First Class的存在, 也就是所谓的第一公民, 闭包(Closures)是这个title所享有的特殊性质, 基于此性质的装饰器应用非常广泛, 常见的Flask中的router就是使用了装饰器.

基于装饰器产生了一种叫AOP(Aspect Oriented Programming)的编程方式, 与传统的OOP编程思想区别在于, OOP通过类与对象组织代码, 而AOP则对函数按功能切片, 通过注册装饰器的方式来组织代码.

例如在Web开发中, 需要对系统某些模块添加验证或其他功能, 如果是OOP的话得要挨个修改view函数, 不仅徒增代码冗余, 而且对原有代码具有侵入性. 而AOP的话直接将要添加的逻辑定义成一个装饰器, 在指定的view函数注册装饰器即可, 不破坏原有代码逻辑, 简洁优雅.

那什么是闭包呢? 要理解闭包我们需要清楚以下几个概念:

函数的作用域:

作用域即函数的namespace命名空间,python在遇到一个函数的时候会新建一个作用域,在函数中调用变量的时候会优先在自己的作用域中查找,如果找不到则向外层作用域继续找, 如果全局作用域都找不到该变量就抛出异常

函数变量的生命周期:

函数的变量在函数执行时创建,函数执行完后销毁,如下图所示 函数变量在test函数执行完后已经销毁,后续代码访问 ‘x’变量会导致出错:

闭包:

在Python 的世界里, 一切皆对象的思想贯穿始终, 函数也是对象, 函数可以直接执行, 也可以被引用, 可以嵌套, 甚至可以作为返回值被返回 (这在C语言里是不可想象的), 以下一个简单例子理解闭包:

上图中的outer函数内定义了一个inner的函数,outer返回的是内层函数,按道理来说变量x是在外层函数定义的,那么在外层函数返回之后变量x就被销毁而不应该被inner函数访问,即在非全局作用域下定义的inner函数在定义的时候会记住外层命名空间的变量,即inner包含了外层作用域变量!

装饰器:

在上图的例子中,inner函数记住了outer的作用域,也就是说inner能访问到outer的变量,每次运行outer函数时inner函数都会被重新定义,说白了可以把inner函数当作outer函数的函数体,那么如果变量x是从外部传入的话能够在保持inner函数的情况下为该函数增加一些功能,这就是装饰器的作用,在不改变原有函数结构的情况下增加新的功能,比如常用的为函数增加打印运行时间的功能:

如上图所示:decorater函数里定义了inner函数,其本身接受一个函数作为参数,在inner函数内部执行待传入的函数,test是测试函数,new_test是添加了打印参数功能的新函数,上面的装饰器使用不是很方便,python有个@的语法糖,底层不变但是方便了程序员:

仔细观察上面的代码我们发现, 装饰器本身就是一个函数, 它接受一个可调用对象作为其参数, 然后输出一个新的可调用对象, 可不可以用类来实现呢? 可以的, 只要把类本身变成一个可执行对象, 在__init__方法接收传入的参数, 然后重载__call__方法, 在call方法中调用被包装的函数即可:

但是如果需要一个含有参数的装饰器的话, 就不太一样了, __init__ 方法接收装饰器的参数, 然后 __call__方法传入被装饰函数:

总结:

本文大致总结了我对Python闭包和装饰器的一些理解, 闭包能扩展函数的能力, 在一些函数作为一等公民的语言大都支持闭包, JavaScript甚至能用函数的原型继承模拟出一套OOP的编程方式! 当然我觉得还是Python实现得更优雅一点...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值