如何正确理解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实现简单字典树的方法
Apr 29 Python
Selenium的使用详解
Oct 19 Python
Python拼接字符串的7种方法总结
Nov 01 Python
Python 做曲线拟合和求积分的方法
Dec 29 Python
使用python的pexpect模块,实现远程免密登录的示例
Feb 14 Python
Python3.5 Pandas模块缺失值处理和层次索引实例详解
Apr 23 Python
使用python telnetlib批量备份交换机配置的方法
Jul 25 Python
解决pycharm不能自动补全第三方库的函数和属性问题
Mar 12 Python
PyQt5中向单元格添加控件的方法示例
Mar 24 Python
python3+opencv 使用灰度直方图来判断图片的亮暗操作
Jun 02 Python
利用Python第三方库实现预测NBA比赛结果
Jun 21 Python
python模板入门教程之flask Jinja
Apr 11 Python
详解python网络进程
整理Python中常用的conda命令操作
Python实现单例模式的5种方法
Jun 15 #Python
用Python爬取某乎手机APP数据
七个非常实用的Python工具包总结
python异常中else的实例用法
Jun 15 #Python
Python实现简单的猜单词
You might like
php 目录遍历、删除 函数的使用介绍
2013/04/28 PHP
基于session_unset与session_destroy的区别详解
2013/06/03 PHP
PHP register_shutdown_function()函数的使用示例
2015/06/23 PHP
laravel项目利用twemproxy部署redis集群的完整步骤
2018/05/11 PHP
使用IE的地址栏来辅助调试Web页脚本
2007/03/08 Javascript
JavaScript 10件让人费解的事情
2010/02/15 Javascript
jquery ui resizable bug解决方法
2010/10/26 Javascript
JS随即打乱数组实现代码
2012/12/03 Javascript
jQuery中ajax的load()方法用法实例
2014/12/26 Javascript
jQuery实现折叠、展开的菜单组效果代码
2015/09/16 Javascript
使用JSON作为函数的参数的优缺点
2016/10/27 Javascript
js与jquery分别实现tab标签页功能的方法
2016/11/18 Javascript
JavaScript中利用构造器函数模拟类的方法
2017/02/16 Javascript
Javascript 一些需要注意的细节(必看篇)
2017/07/08 Javascript
微信小程序js文件改变参数并在视图上及时更新【推荐】
2018/06/11 Javascript
在vue-cli创建的项目中使用sass操作
2020/08/10 Javascript
python fabric使用笔记
2015/05/09 Python
详解Python中 __get__和__getattr__和__getattribute__的区别
2016/06/16 Python
Python使用tkinter模块实现推箱子游戏
2019/10/08 Python
python机器学习实现决策树
2019/11/11 Python
细数nn.BCELoss与nn.CrossEntropyLoss的区别
2020/02/29 Python
python GUI库图形界面开发之PyQt5简单绘图板实例与代码分析
2020/03/08 Python
定义css设备类型-Media Queries图表简介及使用方法
2013/01/21 HTML / CSS
CSS3颜色值RGBA与渐变色使用介绍
2020/03/06 HTML / CSS
英国网上电器商店:Electricshop
2020/03/15 全球购物
餐饮业员工工作决心书
2014/03/11 职场文书
2014第二批党员干部对照“四风”找差距检查材料思想汇报
2014/09/18 职场文书
国庆节促销广告语2014
2014/09/19 职场文书
乡镇干部个人整改措施思想汇报
2014/10/10 职场文书
群众路线领导班子整改方案
2014/10/25 职场文书
质量承诺书格式范文
2015/04/28 职场文书
城镇居民医疗保险工作总结
2015/08/10 职场文书
学校教师培训工作总结
2015/10/14 职场文书
公证书
2019/04/17 职场文书
互联网的下一个风口:新的独角兽将诞生
2019/08/02 职场文书
导游词之日月潭
2019/11/05 职场文书