如何正确理解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中global与nonlocal比较
Nov 21 Python
使用python调用zxing库生成二维码图片详解
Jan 10 Python
基于Python的XSS测试工具XSStrike使用方法
Jul 29 Python
python实现数据图表
Jul 29 Python
Python3中条件控制、循环与函数的简易教程
Nov 21 Python
python爬取微信公众号文章
Aug 31 Python
python 多线程将大文件分开下载后在合并的实例
Nov 09 Python
浅谈Scrapy网络爬虫框架的工作原理和数据采集
Feb 07 Python
python如何实现不可变字典inmutabledict
Jan 08 Python
使用python创建生成动态链接库dll的方法
May 09 Python
Python经典五人分鱼实例讲解
Jan 04 Python
python opencv将多个图放在一个窗口的实例详解
Feb 28 Python
详解python网络进程
整理Python中常用的conda命令操作
Python实现单例模式的5种方法
Jun 15 #Python
用Python爬取某乎手机APP数据
七个非常实用的Python工具包总结
python异常中else的实例用法
Jun 15 #Python
Python实现简单的猜单词
You might like
php 静态属性和静态方法区别详解
2017/04/09 PHP
基于laravel-admin 后台 列表标签背景的使用方法
2019/10/03 PHP
js实现拉伸拖动iframe的具体代码
2013/08/03 Javascript
关于js中for in的缺陷浅析
2013/12/02 Javascript
JS实现图片剪裁并预览效果
2016/08/12 Javascript
基于JS实现弹出一个隐藏的div窗口body页面变成灰色并且不可被编辑
2016/12/14 Javascript
BootstrapTable请求数据时设置超时(timeout)的方法
2017/01/22 Javascript
jquery实时获取时间的简单实例
2017/01/26 Javascript
js/jq仿window文件夹移动/剪切/复制等操作代码
2017/03/08 Javascript
JavaScript数据结构之二叉树的删除算法示例
2017/04/13 Javascript
vue自定义全局组件(自定义插件)的用法
2018/01/30 Javascript
vue中手机号,邮箱正则验证以及60s发送验证码的实例
2018/03/16 Javascript
vue2.0 移动端实现下拉刷新和上拉加载更多的示例
2018/04/23 Javascript
vue微信分享的实现(在当前页面分享其他页面)
2019/04/16 Javascript
JavaScript实现单英文金山打字通
2020/07/24 Javascript
小程序双头slider选择器的实现示例
2020/03/31 Javascript
梳理一下vue中的生命周期
2020/12/30 Vue.js
python实现数通设备tftp备份配置文件示例
2014/04/02 Python
使用Python设置tmpfs来加速项目的教程
2015/04/17 Python
Python和C/C++交互的几种方法总结
2017/05/11 Python
python urllib urlopen()对象方法/代理的补充说明
2017/06/29 Python
python筛选出两个文件中重复行的方法
2018/05/31 Python
python爬取哈尔滨天气信息
2018/07/14 Python
Python如何处理大数据?3个技巧效率提升攻略(推荐)
2019/04/15 Python
python匿名函数的使用方法解析
2019/10/10 Python
Html5实现单张、多张图片上传功能
2019/04/28 HTML / CSS
使用css3 属性如何丰富图片样式(圆角 阴影 渐变)
2012/11/22 HTML / CSS
美国高端寝具品牌:Coyuchi
2017/02/08 全球购物
英国时尚运动品牌的合集:The Sports Edit
2017/12/20 全球购物
Lookfantastic俄罗斯:欧洲在线化妆品零售商
2019/08/06 全球购物
校园学雷锋活动月总结
2014/03/09 职场文书
学校课外活动总结
2014/05/08 职场文书
卖房协议书样本
2014/10/30 职场文书
入党宣誓大会后的感想
2015/08/10 职场文书
幼儿园园长新年寄语
2015/08/17 职场文书
2016领导干部廉洁自律心得体会
2016/01/13 职场文书