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的Twisted框架实现webshell密码扫描器的教程
Apr 16 Python
Python自动重试HTTP连接装饰器
Apr 28 Python
Python获取任意xml节点值的方法
May 05 Python
Python基于动态规划算法计算单词距离
Jul 25 Python
Python通过matplotlib画双层饼图及环形图简单示例
Dec 15 Python
python中从str中提取元素到list以及将list转换为str的方法
Jun 26 Python
简单了解python变量的作用域
Jul 30 Python
Django ORM多对多查询方法(自定义第三张表&ManyToManyField)
Aug 09 Python
Python3.7 读取 mp3 音频文件生成波形图效果
Nov 05 Python
Python3+RIDE+RobotFramework自动化测试框架搭建过程详解
Sep 23 Python
python安装mysql的依赖包mysql-python操作
Jan 01 Python
python中封包建立过程实例
Feb 18 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中的(伪)多线程与多进程
2013/07/01 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(八)
2014/06/23 PHP
PHP使用http_build_query()构造URL字符串的方法
2016/04/02 PHP
PHP5.5.15+Apache2.4.10+MySQL5.6.20配置方法分享
2016/05/06 PHP
js创建元素(节点)示例
2014/01/02 Javascript
JS简单操作select和dropdownlist实例
2014/11/26 Javascript
Query常用DIV操作获取和设置长度宽度的实现方法
2016/09/19 Javascript
Canvas 制作动态进度加载水球详解及实例代码
2016/12/09 Javascript
JS查找字符串中出现最多的字符及个数统计
2017/02/04 Javascript
微信小程序开发之相册选择和拍照详解及实例代码
2017/02/22 Javascript
ES6中的rest参数与扩展运算符详解
2017/07/18 Javascript
Mac中安装nvm的教程分享
2017/12/11 Javascript
vue todo-list组件发布到npm上的方法
2018/04/04 Javascript
微信小程序返回上一页传参并刷新过程解析
2019/12/13 Javascript
vue实现放大镜效果
2020/09/17 Javascript
JSON stringify方法原理及实例解析
2020/10/23 Javascript
vue 解决provide和inject响应的问题
2020/11/12 Javascript
[07:57]DOTA2热力大趴狂欢夜 广州站活动回顾
2013/11/27 DOTA
python中numpy的矩阵、多维数组的用法
2018/02/05 Python
pandas 数据结构之Series的使用方法
2019/06/21 Python
pycharm 批量修改变量名称的方法
2019/08/01 Python
pytorch 更改预训练模型网络结构的方法
2019/08/19 Python
Django用户身份验证完成示例代码
2020/04/03 Python
简单了解python列表和元组的区别
2020/05/14 Python
浅谈Keras参数 input_shape、input_dim和input_length用法
2020/06/29 Python
Django与AJAX实现网页动态数据显示的示例代码
2021/02/24 Python
美国折扣地毯销售网站:Rugs.com
2020/03/27 全球购物
ajax是什么及其工作原理
2012/02/08 面试题
留学经费担保书
2014/05/12 职场文书
机关驾驶员违规检讨书
2014/09/13 职场文书
环卫工作汇报材料
2014/10/28 职场文书
挂职个人工作总结
2015/03/05 职场文书
四风之害观后感
2015/06/09 职场文书
python函数的两种嵌套方法使用
2022/04/02 Python
Apache Kafka 分区重分配的实现原理解析
2022/07/15 Servers
mysqldump进行数据备份详解
2022/07/15 MySQL