如何正确理解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字符转换
Sep 06 Python
python之matplotlib学习绘制动态更新图实例代码
Jan 23 Python
django 发送邮件和缓存的实现代码
Jul 18 Python
python 实现敏感词过滤的方法
Jan 21 Python
Python中文编码知识点
Feb 18 Python
python读写csv文件的方法
Aug 13 Python
18个Python脚本可加速你的编码速度(提示和技巧)
Oct 17 Python
python的launcher用法知识点总结
Aug 07 Python
Python logging自定义字段输出及打印颜色
Nov 30 Python
python中count函数知识点浅析
Dec 17 Python
python实战之一步一步教你绘制小猪佩奇
Apr 22 Python
python APScheduler执行定时任务介绍
Apr 19 Python
详解python网络进程
整理Python中常用的conda命令操作
Python实现单例模式的5种方法
Jun 15 #Python
用Python爬取某乎手机APP数据
七个非常实用的Python工具包总结
python异常中else的实例用法
Jun 15 #Python
Python实现简单的猜单词
You might like
PHP函数篇之掌握ord()与chr()函数应用
2011/12/05 PHP
基于PHP编程注意事项的小结
2013/04/27 PHP
Destoon模板制作简明教程
2014/06/20 PHP
PHP实现一个简单url路由功能实例
2016/11/05 PHP
Windows平台实现PHP连接SQL Server2008的方法
2017/07/26 PHP
php获取ajax的headers方法与内容实例
2017/12/27 PHP
浅谈Laravel POST,PUT,PATCH 路由的区别
2019/10/15 PHP
jQuery 位置插件
2008/12/25 Javascript
JQuery 初体验(建议学习jquery)
2009/04/25 Javascript
Javascript 通过json自动生成Dom的代码
2010/04/01 Javascript
在JavaScript中使用timer示例
2014/05/08 Javascript
js获取checkbox复选框选中的选项实例
2014/08/24 Javascript
基于javascript实现tab选项卡切换特效调试笔记
2016/03/30 Javascript
Jquery Easyui菜单组件Menu使用详解(15)
2016/12/18 Javascript
vue axios整合使用全攻略
2018/05/24 Javascript
vue element table 表格请求后台排序的方法
2018/09/28 Javascript
微信小程序实现购物页面左右联动
2019/02/15 Javascript
微信小程序使用蓝牙小插件
2019/09/23 Javascript
Python程序员鲜为人知但你应该知道的17个问题
2014/06/04 Python
python使用sorted函数对列表进行排序的方法
2015/04/04 Python
Python 实现淘宝秒杀的示例代码
2018/01/02 Python
pandas 根据列的值选取所有行的示例
2018/11/07 Python
Python猫眼电影最近上映的电影票房信息
2020/09/18 Python
HTML5 Canvas绘制五星红旗
2016/05/04 HTML / CSS
台湾深度自由行旅游平台:Tripbaa趣吧
2017/10/10 全球购物
AVI-8手表美国官方商店:AVI-8 USA
2019/04/10 全球购物
新书发布会策划方案
2014/06/09 职场文书
医学专业自荐信
2014/06/14 职场文书
2014年党员加强作风建设思想汇报
2014/09/15 职场文书
2014小学二年级班主任工作总结
2014/12/05 职场文书
2015年教师自我评价范文
2015/03/04 职场文书
公积金贷款承诺书
2015/04/30 职场文书
老员工辞职信范文
2015/05/12 职场文书
观看《杨善洲》宣传教育片心得体会
2016/01/23 职场文书
numpy数据类型dtype转换实现
2021/04/24 Python
Spring事务管理下synchronized锁失效问题的解决方法
2022/03/31 Java/Android