如何正确理解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中的hashlib和base64加密模块使用实例
Sep 02 Python
Python实现配置文件备份的方法
Jul 30 Python
Python字符串处理实现单词反转
Jun 14 Python
Python实现破解猜数游戏算法示例
Sep 25 Python
使用python编写简单的小程序编译成exe跑在win10上
Jan 15 Python
对python append 与浅拷贝的实例讲解
May 04 Python
python3使用flask编写注册post接口的方法
Dec 28 Python
程序员的七夕用30行代码让Python化身表白神器
Aug 07 Python
python 实现生成均匀分布的点
Dec 05 Python
Python求平面内点到直线距离的实现
Jan 19 Python
Pyecharts 中Geo函数常用参数的用法说明
Feb 01 Python
教你利用Selenium+python自动化来解决pip使用异常
May 20 Python
详解python网络进程
整理Python中常用的conda命令操作
Python实现单例模式的5种方法
Jun 15 #Python
用Python爬取某乎手机APP数据
七个非常实用的Python工具包总结
python异常中else的实例用法
Jun 15 #Python
Python实现简单的猜单词
You might like
两个强悍的php 图像处理类1
2009/06/15 PHP
laravel实现查询最后执行的一条sql语句的方法
2019/10/09 PHP
基于jQuery的动态增删改查表格信息,可左键/右键提示(原创自Zjmainstay)
2012/07/31 Javascript
jQuery 获取、设置HTML或TEXT内容的两种方法
2014/05/23 Javascript
jQuery常用数据处理方法小结
2015/02/20 Javascript
vue2 如何实现div contenteditable=“true”(类似于v-model)的效果
2017/02/08 Javascript
jQuery Chosen通用初始化
2017/03/07 Javascript
基于canvas粒子系统的构建详解
2017/08/31 Javascript
原生JS实现瀑布流插件
2018/02/06 Javascript
详解在React里使用"Vuex"
2018/04/02 Javascript
详解基于Vue-cli搭建的项目如何和后台交互
2018/06/29 Javascript
JS实现用特殊符号替换字符串的中间部分区域的实例代码
2018/07/24 Javascript
解决vuejs项目里css引用背景图片不能显示的问题
2018/09/13 Javascript
JQuery实现ajax请求的示例和注意事项
2018/12/10 jQuery
小程序按钮避免多次调用接口和点击方案实现(不用showLoading)
2020/04/15 Javascript
在HTML中使用JavaScript的两种方法
2020/12/24 Javascript
[04:52]DOTA2亚洲邀请赛附加赛 TOP10精彩集锦
2015/01/29 DOTA
[01:52]深扒TI7聊天轮盘语音出处7
2017/05/11 DOTA
在Python中处理列表之reverse()方法的使用教程
2015/05/21 Python
Python解惑之整数比较详解
2017/04/24 Python
一个月入门Python爬虫学习,轻松爬取大规模数据
2018/01/03 Python
python如何在循环引用中管理内存
2018/03/20 Python
python flask框架实现传数据到js的方法分析
2019/06/11 Python
pandas 使用均值填充缺失值列的小技巧分享
2019/07/04 Python
从numpy数组中取出满足条件的元素示例
2019/11/26 Python
学python最电脑配置有要求么
2020/07/05 Python
Matplotlib animation模块实现动态图
2021/02/25 Python
英国家居装饰品、户外家具和玻璃器皿购物网站:Rinkit.com
2019/11/04 全球购物
GWebs公司笔试题
2012/05/04 面试题
药物学专业学生的自我评价
2013/10/27 职场文书
年度考核评语
2014/01/19 职场文书
2014年大学生党员评议表自我评价
2014/09/20 职场文书
4S店客服专员岗位职责
2015/04/07 职场文书
小学教师教学随笔
2015/08/14 职场文书
解析laravel使用workerman用户交互、服务器交互
2021/04/28 PHP
MySQL中int (10) 和 int (11) 的区别
2022/01/22 MySQL