如何正确理解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读写文件操作示例程序
Dec 02 Python
简单介绍Python中的RSS处理
Apr 13 Python
理解Python垃圾回收机制
Feb 12 Python
Python实现图片转字符画的示例
Aug 22 Python
python中的for循环
Sep 28 Python
详解Python中正则匹配TAB及空格的小技巧
Jul 26 Python
python求加权平均值的实例(附纯python写法)
Aug 22 Python
Python如何实现强制数据类型转换
Nov 22 Python
python序列化与数据持久化实例详解
Dec 20 Python
pandas实现DataFrame显示最大行列,不省略显示实例
Dec 26 Python
pytorch中tensor张量数据类型的转化方式
Dec 31 Python
Python Matplotlib绘制两个Y轴图像
Apr 13 Python
详解python网络进程
整理Python中常用的conda命令操作
Python实现单例模式的5种方法
Jun 15 #Python
用Python爬取某乎手机APP数据
七个非常实用的Python工具包总结
python异常中else的实例用法
Jun 15 #Python
Python实现简单的猜单词
You might like
php设计模式 Prototype (原型模式)代码
2011/06/26 PHP
深入解析yii权限分级式访问控制的实现(非RBAC法)
2013/06/13 PHP
PHP中使用imagick生成PSD文件缩略图教程
2015/01/26 PHP
php支付宝手机网页支付类实例
2015/03/04 PHP
Javascript this关键字使用分析
2008/10/21 Javascript
关于javascript function对象那些迷惑分析
2011/10/24 Javascript
javascript中apply、call和bind的使用区别
2016/04/05 Javascript
Vue服务端渲染和Vue浏览器端渲染的性能对比(实例PK )
2017/03/31 Javascript
详解nodejs操作mongodb数据库封装DB类
2017/04/10 NodeJs
微信小程序实现皮肤功能(夜间模式)
2017/06/18 Javascript
Vue.use()在new Vue() 之前使用的原因浅析
2019/08/26 Javascript
在vue项目中利用popstate处理页面返回的操作介绍
2020/08/06 Javascript
vue 中this.$set 动态绑定数据的案例讲解
2021/01/29 Vue.js
[02:27]刀塔重生降临
2015/10/14 DOTA
Python中声明只包含一个元素的元组数据方法
2014/08/25 Python
Python 模拟员工信息数据库操作的实例
2017/10/23 Python
python通过伪装头部数据抵抗反爬虫的实例
2018/05/07 Python
Pyspider中给爬虫伪造随机请求头的实例
2018/05/07 Python
Python tkinter的grid布局及Text动态显示方法
2018/10/11 Python
python使用adbapi实现MySQL数据库的异步存储
2019/03/19 Python
Python socket模块实现的udp通信功能示例
2019/04/10 Python
Python 窗体(tkinter)按钮 位置实例
2019/06/13 Python
django 捕获异常和日志系统过程详解
2019/07/18 Python
Pytorch 搭建分类回归神经网络并用GPU进行加速的例子
2020/01/09 Python
pytorch-RNN进行回归曲线预测方式
2020/01/14 Python
Python 程序报错崩溃后如何倒回到崩溃的位置(推荐)
2020/06/23 Python
python 生成正态分布数据,并绘图和解析
2020/12/21 Python
HTML5 input placeholder 颜色修改示例
2014/05/30 HTML / CSS
HTML5 video标签(播放器)学习笔记(一):使用入门
2015/04/24 HTML / CSS
Smashbox官网:美国知名彩妆品牌
2017/01/05 全球购物
吉列剃须刀英国官网:Gillette英国
2019/03/28 全球购物
中学生在校期间的自我评价分享
2013/11/13 职场文书
房地产出纳岗位职责
2013/12/01 职场文书
大学生创业计划书的范文
2014/01/07 职场文书
《浅水洼里的小鱼》教学反思
2016/02/16 职场文书
pytorch交叉熵损失函数的weight参数的使用
2021/05/24 Python