如何正确理解python装饰器


Posted in Python onJune 15, 2021

一、闭包

要想了解装饰器,首先要了解一个概念,闭包。什么是闭包,一句话说就是,在函数中再嵌套一个函数,并且引用外部函数的变量,这就是一个闭包了。光说没有概念,直接上一个例子。

def outer(x):
    def inner(y):
        return x + y
    return inner

print(outer(6)(5))
-----------------------------
>>>11

如代码所示,在outer函数内,又定义了一个inner函数,并且inner函数又引用了外部函数outer的变量x,这就是一个闭包了。在输出时,outer(6)(5),第一个括号传进去的值返回inner函数,其实就是返回6 + y,所以再传第二个参数进去,就可以得到返回值,6 + 5。

二、装饰器

接下来就讲装饰器,其实装饰器就是一个闭包,装饰器是闭包的一种应用。什么是装饰器呢,简言之,python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能。使用时,再需要的函数前加上@demo即可。

def debug(func):
    def wrapper():
        print("[DEBUG]: enter {}()".format(func.__name__))
        return func()
    return wrapper

@debug
def hello():
    print("hello")

hello()
-----------------------------
>>>[DEBUG]: enter hello()
>>>hello

例子中的装饰器给函数加上一个进入函数的debug模式,不用修改原函数代码就完成了这个功能,可以说是很方便了。

三、带参数的装饰器

上面例子中的装饰器是不是功能太简单了,那么装饰器可以加一些参数吗,当然是可以的,另外装饰的函数当然也是可以传参数的。

def logging(level):
    def outwrapper(func):
        def wrapper(*args, **kwargs):
            print("[{0}]: enter {1}()".format(level, func.__name__))
            return func(*args, **kwargs)
        return wrapper
    return outwrapper

@logging(level="INFO")
def hello(a, b, c):
    print(a, b, c)

hello("hello,","good","morning")
-----------------------------
>>>[INFO]: enter hello()
>>>hello, good morning

如上,装饰器中可以传入参数,先形成一个完整的装饰器,然后再来装饰函数,当然函数如果需要传入参数也是可以的,用不定长参数符号就可以接收,例子中传入了三个参数。

四、类装饰器

装饰器也不一定只能用函数来写,也可以使用类装饰器,用法与函数装饰器并没有太大区别,实质是使用了类方法中的__call__魔法方法来实现类的直接调用。

class logging(object):
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print("[DEBUG]: enter {}()".format(self.func.__name__))
        return self.func(*args, **kwargs)

@logging
def hello(a, b, c):
    print(a, b, c)

hello("hello,","good","morning")
-----------------------------
>>>[DEBUG]: enter hello()
>>>hello, good morning

类装饰器也是可以带参数的,如下实现

class logging(object):
    def __init__(self, level):
        self.level = level

    def __call__(self, func):
        def wrapper(*args, **kwargs):
            print("[{0}]: enter {1}()".format(self.level, func.__name__))
            return func(*args, **kwargs)
        return wrapper
        
@logging(level="TEST")
def hello(a, b, c):
    print(a, b, c)

hello("hello,","good","morning")
-----------------------------
>>>[TEST]: enter hello()
>>>hello, good morning

好了,如上就是装饰器的一些概念和大致的用法啦,想更深入的了解装饰器还是需要自己在平时的练习和应用中多体会

以上就是如何正确理解python装饰器的详细内容,更多关于python装饰器的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python标准库os.path包、glob包使用实例
Nov 25 Python
Python正则表达式和元字符详解
Nov 29 Python
Python数据可视化库seaborn的使用总结
Jan 15 Python
详解Python匿名函数(lambda函数)
Apr 19 Python
selenium处理元素定位点击无效问题
Jun 12 Python
Python函数中的可变长参数详解
Sep 12 Python
Python实现动态给类和对象添加属性和方法操作示例
Feb 29 Python
pycharm下配置pyqt5的教程(anaconda虚拟环境下+tensorflow)
Mar 25 Python
基于PyTorch的permute和reshape/view的区别介绍
Jun 18 Python
Python常用库Numpy进行矩阵运算详解
Jul 21 Python
Python Request类源码实现方法及原理解析
Aug 17 Python
python中mongodb包操作数据库
Apr 19 Python
详解python网络进程
整理Python中常用的conda命令操作
Python实现单例模式的5种方法
Jun 15 #Python
用Python爬取某乎手机APP数据
七个非常实用的Python工具包总结
python异常中else的实例用法
Jun 15 #Python
Python实现简单的猜单词
You might like
php查看一个变量的占用内存的实例代码
2020/03/29 PHP
深入理解PHP+Mysql分布式事务与解决方案
2020/12/03 PHP
js实现简单模态窗口,背景灰显
2008/11/14 Javascript
新鲜出炉的js tips提示效果
2011/04/03 Javascript
EasyUI的treegrid组件动态加载数据问题的解决办法
2011/12/11 Javascript
关于JQuery($.load)事件的用法和分析
2013/04/09 Javascript
浅谈Sizzle的“编译原理”
2015/04/14 Javascript
bootstrap fileinput组件整合Springmvc上传图片到本地磁盘
2017/05/11 Javascript
vue数据传递--我有特殊的实现技巧
2018/03/20 Javascript
Vue2.0学习系列之项目上线的方法步骤(图文)
2018/09/25 Javascript
Nodejs中获取当前函数被调用的行数及文件名详解
2018/12/12 NodeJs
关于layui 弹出层一闪而过就消失的解决方法
2019/09/09 Javascript
Vue 利用指令实现禁止反复发送请求的两种方法
2019/09/15 Javascript
微信小程序实现点击按钮后修改颜色
2019/12/05 Javascript
vue组件是如何解析及渲染的?
2021/01/13 Vue.js
Python生成器(Generator)详解
2015/04/13 Python
Flask框架web开发之零基础入门
2018/12/10 Python
python读取并写入mat文件的方法
2019/07/12 Python
django 环境变量配置过程详解
2019/08/06 Python
python使用HTMLTestRunner导出饼图分析报告的方法
2019/12/30 Python
简单掌握CSS3将文字描边及填充文字颜色的方法
2016/03/07 HTML / CSS
用React加CSS3实现微信拆红包动画效果
2017/03/13 HTML / CSS
浅谈html5 video 移动端填坑记
2018/01/15 HTML / CSS
美国名牌手表折扣网站:Jomashop
2020/05/22 全球购物
国际经济贸易专业推荐信
2013/11/06 职场文书
令人啧啧称赞的经理推荐信
2013/11/07 职场文书
元旦文艺汇演主持词
2014/03/26 职场文书
2015年团队工作总结范文
2015/05/04 职场文书
离开雷锋的日子观后感
2015/06/09 职场文书
2015教师个人德育工作总结
2015/07/22 职场文书
Python打包为exe详细教程
2021/05/18 Python
Keras多线程机制与flask多线程冲突的解决方案
2021/05/28 Python
vue.js Router中嵌套路由的实用示例
2021/06/27 Vue.js
SpringBoot+Vue+JWT的前后端分离登录认证详细步骤
2021/09/25 Java/Android
win10清理dns缓存
2022/04/19 数码科技
基于Redission的分布式锁实战
2022/08/14 Redis