如何正确理解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自定义类的数组排序实现代码
Aug 28 Python
教大家玩转Python字符串处理的七种技巧
Mar 31 Python
python utc datetime转换为时间戳的方法
Jan 15 Python
Python实现多进程的四种方式
Feb 22 Python
Python3利用print输出带颜色的彩色字体示例代码
Apr 08 Python
Python使用LDAP做用户认证的方法
Jun 20 Python
python turtle库画一个方格和圆实例
Jun 27 Python
python ImageDraw类实现几何图形的绘制与文字的绘制
Feb 26 Python
python求解汉诺塔游戏
Jul 09 Python
如何利用Python 进行边缘检测
Oct 14 Python
多个版本的python共存时使用pip的正确做法
Oct 26 Python
正确的理解和使用Django信号(Signals)
Apr 14 Python
详解python网络进程
整理Python中常用的conda命令操作
Python实现单例模式的5种方法
Jun 15 #Python
用Python爬取某乎手机APP数据
七个非常实用的Python工具包总结
python异常中else的实例用法
Jun 15 #Python
Python实现简单的猜单词
You might like
PHP详解ASCII码对照表与字符转换
2011/12/05 PHP
深入PHP与浏览器缓存的分析
2013/06/03 PHP
Php output buffering缓存及程序缓存深入解析
2013/07/15 PHP
php+memcache实现的网站在线人数统计代码
2014/07/04 PHP
PHP生成器简单实例
2015/05/13 PHP
Win10 下安装配置IIS + MySQL + nginx + php7.1.7
2017/08/04 PHP
JS解密入门之凭直觉解
2008/06/25 Javascript
Javascript 遮罩层和加载效果代码
2013/08/01 Javascript
基于jQuery+Cookie实现的防止刷新的在线考试倒计时
2015/06/19 Javascript
简介alert()与console.log()的不同
2015/08/26 Javascript
jQuery实现仿QQ在线客服效果的滚动层代码
2015/10/15 Javascript
JavaScript中实现无缝滚动、分享到侧边栏实例代码
2016/04/06 Javascript
基于jQuery插件实现点击小图显示大图效果
2016/05/11 Javascript
js图片上传前预览功能(兼容所有浏览器)
2016/08/24 Javascript
javascript 将共享属性迁移到原型中去的实现方法
2016/08/31 Javascript
Bootstrap超大屏幕的实现代码
2017/03/22 Javascript
详解JavaScript对象的深浅复制
2017/03/30 Javascript
在 Node.js 中使用原生 ES 模块方法解析
2017/09/19 Javascript
浅谈vue单一组件下动态修改数据时的全部重渲染
2018/03/01 Javascript
Nodejs实现图片上传、压缩预览、定时删除功能
2019/10/25 NodeJs
如何修改Vue打包后文件的接口地址配置的方法
2020/04/22 Javascript
原生js生成图片验证码
2020/10/11 Javascript
vue+iview实现分页及查询功能
2020/11/17 Vue.js
python获取文件后缀名及批量更新目录下文件后缀名的方法
2014/11/11 Python
python字典排序的方法
2019/10/12 Python
在pytorch中实现只让指定变量向后传播梯度
2020/02/29 Python
Python中的Cookie模块如何使用
2020/06/04 Python
python和c语言哪个更适合初学者
2020/06/22 Python
利用python+ffmpeg合并B站视频及格式转换的实例代码
2020/11/24 Python
详解Css3新特性应用之过渡与动画
2017/01/10 HTML / CSS
外贸主管求职简历的自我评价
2013/10/23 职场文书
主题党日活动总结
2014/07/08 职场文书
2014年青年教师工作总结
2014/12/17 职场文书
六年级数学教学反思
2016/02/16 职场文书
深度学习详解之初试机器学习
2021/04/14 Python
python lambda 表达式形式分析
2022/04/03 Python