如何正确理解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二叉树的实现实例
Nov 21 Python
python3.3教程之模拟百度登陆代码分享
Jan 16 Python
python检索特定内容的文本文件实例
Jun 05 Python
numpy.std() 计算矩阵标准差的方法
Jul 11 Python
Python实现将Excel转换成xml的方法示例
Aug 25 Python
Python 比较文本相似性的方法(difflib,Levenshtein)
Oct 15 Python
python3实现点餐系统
Jan 24 Python
Python 分发包中添加额外文件的方法
Aug 16 Python
python 实现turtle画图并导出图片格式的文件
Dec 07 Python
Scrapy爬虫文件批量运行的实现
Sep 30 Python
浅析Python中字符串的intern机制
Oct 03 Python
python中delattr删除对象方法的代码分析
Dec 15 Python
详解python网络进程
整理Python中常用的conda命令操作
Python实现单例模式的5种方法
Jun 15 #Python
用Python爬取某乎手机APP数据
七个非常实用的Python工具包总结
python异常中else的实例用法
Jun 15 #Python
Python实现简单的猜单词
You might like
PHP的历史和优缺点
2006/10/09 PHP
Cakephp 执行主要流程
2010/03/24 PHP
WordPress中转义HTML与过滤链接的相关PHP函数使用解析
2015/12/22 PHP
apache php mysql开发环境安装教程
2016/07/28 PHP
基于PHP的加载类操作以及其他两种魔术方法的应用实例
2017/08/28 PHP
PHP中quotemeta()函数的用法讲解
2019/04/04 PHP
弹出广告特效(一个IP只弹出一次)的代码
2007/07/27 Javascript
jQuery Ajax 仿AjaxPro.Utility.RegisterTypeForAjax辅助方法
2011/09/27 Javascript
js 一个关于图片onload加载的事
2013/11/10 Javascript
浅谈EasyUI中Treegrid节点的删除
2015/03/01 Javascript
jQuery解析XML与传统JavaScript方法的差别实例分析
2015/03/05 Javascript
举例讲解JavaScript中关于对象操作的相关知识
2015/11/16 Javascript
nodejs 中模拟实现 emmiter 自定义事件
2016/02/22 NodeJs
JS中使用apply、bind实现为函数或者类传入动态个数的参数
2016/04/26 Javascript
微信小程序 两种为对象属性赋值的方式详解
2017/02/23 Javascript
fckeditor部署到weblogic出现xml无法读取及样式不能显示问题的解决方法
2017/03/24 Javascript
在vue2.0中引用element-ui组件库的方法
2018/06/21 Javascript
js实现点击按钮随机生成背景颜色
2020/09/05 Javascript
编程语言Python的发展史
2014/09/26 Python
简单介绍Python中的JSON使用
2015/04/28 Python
python批量下载网站马拉松照片的完整步骤
2018/12/05 Python
python3实现表白神器
2019/04/09 Python
python地震数据可视化详解
2019/06/18 Python
详解Python绘图Turtle库
2019/10/12 Python
python字符串的拼接方法总结
2019/11/18 Python
HTML5 Canvas画线技巧——实现绘制一个像素宽的细线
2013/08/02 HTML / CSS
迪拜航空官方网站:flydubai
2017/04/20 全球购物
丝芙兰中国官方商城:SEPHORA中国
2018/01/10 全球购物
Nayomi官网:沙特阿拉伯王国睡衣和内衣品牌
2020/12/19 全球购物
测控技术与通信工程毕业生自荐信范文
2013/12/28 职场文书
小学向国旗敬礼活动方案
2014/09/27 职场文书
村党建工作汇报材料
2014/11/02 职场文书
表扬稿范文
2015/01/17 职场文书
小学语文新课改心得体会
2016/01/22 职场文书
漫画「狩龙人拉格纳」公开TV动画预告图
2022/03/22 日漫
阿里面试Nacos配置中心交互模型是push还是pull原理解析
2022/07/23 Java/Android