python装饰器代码解析


Posted in Python onMarch 23, 2022

1.装饰器通用模型

def wrapper(fn):
    def inner(*args, **kwargs):
        ret = fn(*args, **kwargs)
        return ret

    return inner

装饰器几个关键点:

  • 1.函数可以当参数传递
  • 2.函数可以作为返回值进行返回
  • 3.函数名称可以当成变量一样进行赋值操作

装饰器本质上是个闭包,在不改变原有函数调用的情况下,给函数增加新的功能

举个例子:

def admin(game):
    def inner(*args, **kwargs):  # inner添加了参数,args 一定是个元组 kwargs 一定是字典
        print('打开Wg')
        result = game(*args, **kwargs)  # * ** 表示把args元组和kwargs打散成位置参数,关键字参数传递进去
        print('关闭Wg')
        return result

    return inner


@admin
def play_dnf(username, password):
    print(f'开始玩DNF,账号:{username},密码:{password}')
    print('刀斩肉身,心斩灵魂')
    return '掉落:戮蛊的哀鸣炮'


@admin
def play_wow(race, occupation, server_name, camp):
    print(f'开始玩魔兽世界,种族:{race},职业:{occupation},服务器:{server_name},阵营:{camp}')
    print('为了辛多雷的荣耀')
    return '掉落:灰烬使者'


if __name__ == '__main__':
    ret1 = play_dnf('大马猴', '888888')
    print(ret1)
    ret2 = play_wow('血精灵', '圣骑士', '回音山', '部落')
    print(ret2)

这代码还是很好懂的,我就不解释了,然后是执行结果如下:

python demo.py
打开Wg
开始玩DNF,账号:大马猴,密码:888888
刀斩肉身,心斩灵魂
关闭Wg
掉落:戮蛊的哀鸣炮
打开Wg
开始玩魔兽世界,种族:血精灵,职业:圣骑士,服务器:回音山,阵营:部落
为了辛多雷的荣耀
关闭Wg
掉落:灰烬使者

Process finished with exit code 0

2.多个装饰器装饰的函数执行

一个函数被多个装饰器装饰,又将如何执行呢?

def wrapper1(fn):
    def inner(*args, **kwargs):
        print('这是w1进入')
        ret = fn(*args, **kwargs)
        print('这是w1出去')
        return ret

    return inner


def wrapper2(fn):
    def inner(*args, **kwargs):
        print('这是w2进入')
        ret = fn(*args, **kwargs)
        print('这是w2出去')
        return ret

    return inner


@wrapper1
@wrapper2
def target():
    print('我是目标')


if __name__ == '__main__':
    target()

直接给出执行顺序:

一个函数被多个装饰器装饰的执行顺序

# w1 w2 target w2 w1

3.带参数的装饰器

装饰器的语法允许我们在调用时,提供其它参数,比如@decorator(a)。这样,就为装饰器的编写和使用提供了更大的灵活性。
(在上面又套了一层函数)
比如,我们可以在装饰器中指定日志的等级,因为不同业务函数可能需要的日志级别是不一样的。

def use_logging(level):
    def decorator(func):
        def wrapper(*args, **kwargs):
            if level == "warn":
                logging.warn("%s is running" % func.__name__)
            elif level == "info":
                logging.info("%s is running" % func.__name__)
            return func(*args)
        return wrapper

    return decorator

@use_logging(level="warn")
def foo(name='foo'):
    print("i am %s" % name)

foo()

4.类装饰器

没错,装饰器不仅可以是函数,还可以是类,相比函数装饰器,类装饰器具有灵活度大、高内聚、封装性等优点。使用类装饰器主要依靠类的__call__方法,当使用 @ 形式将装饰器附加到函数上时,就会调用此方法。

class Foo(object):
    def __init__(self, func):
        self._func = func

    def __call__(self):
        print ('class decorator runing')
        self._func()
        print ('class decorator ending')

@Foo
def bar():
    print ('bar')

bar()

到此这篇关于python装饰器代码解析的文章就介绍到这了,更多相关python装饰器内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python设置windows桌面壁纸的实现代码
Jan 28 Python
python字符串编码识别模块chardet简单应用
Jun 15 Python
在Python的Django框架中为代码添加注释的方法
Jul 16 Python
Python基于回溯法子集树模板解决最佳作业调度问题示例
Sep 08 Python
Python3实现发送QQ邮件功能(文本)
Dec 15 Python
python爬取拉勾网职位数据的方法
Jan 24 Python
利用Python如何生成便签图片详解
Jul 09 Python
妙用itchat! python实现久坐提醒功能
Nov 25 Python
使用Python实现 学生学籍管理系统
Nov 26 Python
python3 使用Opencv打开USB摄像头,配置1080P分辨率的操作
Dec 11 Python
Python编译为二进制so可执行文件实例
Dec 23 Python
Python基础之hashlib模块详解
May 06 Python
基于Python实现将列表数据生成折线图
Python必备技巧之字符数据操作详解
Pytorch中使用ImageFolder读取数据集时忽略特定文件
Mar 23 #Python
Python借助with语句实现代码段只执行有限次
Mar 23 #Python
python3 字符串str和bytes相互转换
Mar 23 #Python
对象析构函数__del__在Python中何时使用
详解Python内置模块Collections
Mar 22 #Python
You might like
php导入导出excel实例
2013/10/25 PHP
phpmailer在服务器上不能正常发送邮件的解决办法
2014/07/08 PHP
yii实现级联下拉菜单的方法
2014/07/31 PHP
PHP中的reflection反射机制测试例子
2014/08/05 PHP
php异常处理方法实例汇总
2015/06/24 PHP
PHP入门教程之使用Mysqli操作数据库的方法(连接,查询,事务回滚等)
2016/09/11 PHP
Aster vs KG BO3 第三场2.19
2021/03/10 DOTA
很好用的js日历算法详细代码
2013/03/07 Javascript
Jquery实现的tab效果可以指定默认显示第几页
2013/10/16 Javascript
javascript 事件处理示例分享
2014/12/31 Javascript
javascript实现页面刷新时自动清空表单并选中的方法
2015/07/18 Javascript
浅析JavaScript中浏览器的兼容问题
2016/04/19 Javascript
Bootstrap在线电子商务网站实战项目5
2016/10/14 Javascript
微信小程序开发之麦克风动画 帧动画 放大 淡出
2017/04/18 Javascript
浅谈node中的exports与module.exports的关系
2017/08/01 Javascript
vue使用axios时关于this的指向问题详解
2017/12/22 Javascript
记一次webapck4 配置文件无效的解决历程
2018/09/19 Javascript
mpvue微信小程序开发之实现一个弹幕评论
2019/11/24 Javascript
[49:11]完美世界DOTA2联赛PWL S3 INK ICE vs DLG 第二场 12.20
2020/12/23 DOTA
在Python中使用zlib模块进行数据压缩的教程
2015/06/26 Python
Python wxPython库消息对话框MessageDialog用法示例
2018/09/03 Python
python实现机器学习之元线性回归
2018/09/06 Python
python发送多人邮件没有展示收件人问题的解决方法
2019/06/21 Python
Django自定义用户登录认证示例代码
2019/06/30 Python
python如何读取bin文件并下发串口
2019/07/05 Python
基于python3 pyQt5 QtDesignner实现窗口化猜数字游戏功能
2019/07/15 Python
matplotlib命令与格式之tick坐标轴日期格式(设置日期主副刻度)
2019/08/06 Python
python 中值滤波,椒盐去噪,图片增强实例
2019/12/18 Python
ETO男装官方网店:ETO Jeans
2019/02/28 全球购物
黄色火烈鸟:De Gele Flamingo
2019/03/18 全球购物
大学班级学风建设方案
2014/05/01 职场文书
医院搬迁方案
2014/06/14 职场文书
销售内勤岗位职责
2015/02/10 职场文书
Python基础数据类型tuple元组的概念与用法
2021/08/02 Python
Java无向树分析 实现最小高度树
2022/04/09 Javascript
python内置模块之上下文管理contextlib
2022/06/14 Python