如何正确理解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超简单解决约瑟夫环问题
May 12 Python
Python中的ctime()方法使用教程
May 22 Python
python检查序列seq是否含有aset中项的方法
Jun 30 Python
python爬虫获取小区经纬度以及结构化地址
Dec 30 Python
对Python3 pyc 文件的使用详解
Feb 16 Python
python实现Dijkstra算法的最短路径问题
Jun 21 Python
如何不用安装python就能在.NET里调用Python库
Jul 12 Python
Python列表删除元素del、pop()和remove()的区别小结
Sep 11 Python
Python 基于wxpy库实现微信添加好友功能(简洁)
Nov 29 Python
在pytorch 中计算精度、回归率、F1 score等指标的实例
Jan 18 Python
Python类如何定义私有变量
Feb 03 Python
Python通过zookeeper实现分布式服务代码解析
Jul 22 Python
详解python网络进程
整理Python中常用的conda命令操作
Python实现单例模式的5种方法
Jun 15 #Python
用Python爬取某乎手机APP数据
七个非常实用的Python工具包总结
python异常中else的实例用法
Jun 15 #Python
Python实现简单的猜单词
You might like
php中用于检测一个地理IP地址是否可用的代码
2012/02/19 PHP
PHP常用函数和常见疑难问题解答
2014/03/05 PHP
php天翼开放平台短信发送接口实现方法
2014/12/22 PHP
php封装的smartyBC类完整实例
2016/10/19 PHP
php中bind_param()函数用法分析
2017/03/28 PHP
thinkPHP5框架自定义验证器实现方法分析
2018/06/11 PHP
PHP常用工具函数小结【移除XSS攻击、UTF8与GBK编码转换等】
2019/04/27 PHP
JavaScript插入动态样式实现代码
2012/02/22 Javascript
JavaScript阻止事件冒泡示例分享
2014/12/28 Javascript
JS运动框架之分享侧边栏动画实例
2015/03/03 Javascript
JavaScript设计模式经典之命令模式
2016/02/24 Javascript
浅析C/C++,Java,PHP,JavaScript,Json数组、对象赋值时最后一个元素后面是否可以带逗号
2016/03/22 Javascript
js拼接html字符串的注意事项
2016/10/13 Javascript
vue-cli webpack 开发环境跨域详解
2017/05/18 Javascript
浅谈node的事件机制
2017/10/09 Javascript
JS实现图片旋转动画效果封装与使用示例
2018/07/09 Javascript
微信小程序实现按字母排列选择城市功能
2019/11/25 Javascript
JavaScript实现Tab选项卡切换
2020/02/13 Javascript
Openlayers学习之地图比例尺控件
2020/09/28 Javascript
[59:53]DOTA2-DPC中国联赛 正赛 VG vs Elephant BO3 第二场 3月6日
2021/03/11 DOTA
python操作sqlite的CRUD实例分析
2015/05/08 Python
Python用Pillow(PIL)进行简单的图像操作方法
2017/07/07 Python
Python3多线程操作简单示例
2018/05/22 Python
在python下使用tensorflow判断是否存在文件夹的实例
2019/06/10 Python
python 判断三个数字中的最大值实例代码
2019/07/24 Python
python 并发下载器实现方法示例
2019/11/22 Python
如何将PySpark导入Python的放实现(2种)
2020/04/26 Python
摩顿布朗英国官方网上商店:奢华沐浴、身体和头发护理
2016/10/29 全球购物
随机分配座位,共50个学生,使学号相邻的同学座位不能相邻
2014/01/18 面试题
岗位竞聘演讲稿范文
2014/04/24 职场文书
反腐倡廉标语
2014/06/24 职场文书
学校安全责任书范本
2014/07/23 职场文书
企业员工集体活动方案
2014/08/17 职场文书
Prometheus 监控MySQL使用grafana展示
2021/08/30 MySQL
Java虚拟机内存结构及编码实战分享
2022/04/07 Java/Android
MySQL时区造成时差问题
2022/04/13 MySQL