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 相关文章推荐
Web服务器框架 Tornado简介
Jul 16 Python
python清除字符串里非字母字符的方法
Jul 02 Python
全面理解Python中self的用法
Jun 04 Python
Python中的字符串查找操作方法总结
Jun 27 Python
使用Python实现windows下的抓包与解析
Jan 15 Python
python 数字类型和字符串类型的相互转换实例
Jul 17 Python
浅述python中深浅拷贝原理
Sep 18 Python
python实现汽车管理系统
Nov 30 Python
Python中如何导入类示例详解
Apr 17 Python
python异步实现定时任务和周期任务的方法
Jun 29 Python
Python代码中如何读取键盘录入的值
May 27 Python
Python代码注释规范代码实例解析
Aug 14 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
DC的38部超级英雄动画电影
2020/03/03 欧美动漫
PHP 身份证号验证函数
2009/05/07 PHP
提高PHP编程效率的53个要点(经验小结)
2010/09/04 PHP
PHP内存缓存Memcached类实例
2014/12/08 PHP
codeigniter显示所有脚本执行时间的方法
2015/03/21 PHP
PHP使用php-resque库配合Redis实现MQ消息队列的教程
2016/06/29 PHP
浅谈PHP中关于foreach使用引用变量的坑
2016/11/14 PHP
仅用[]()+!等符号就足以实现几乎任意Javascript代码
2010/03/01 Javascript
Jquery 获取checkbox的checked问题
2011/11/16 Javascript
在js文件中如何获取basePath处理js路径问题
2013/07/10 Javascript
javascript中的toFixed固定小数位数 简单实例分享
2013/07/12 Javascript
解决json日期格式问题的3种方法
2014/02/02 Javascript
jQuery常用知识点总结以及平时封装常用函数
2016/02/23 Javascript
JavaScript代码实现左右上下自动晃动自动移动
2016/04/08 Javascript
用原生js做单页应用
2017/01/17 Javascript
详解微信小程序 wx.uploadFile 的编码坑
2017/01/23 Javascript
JS库之Three.js 简易入门教程(详解之一)
2017/09/13 Javascript
仿京东快报向上滚动的实例
2017/12/13 Javascript
详解vue移动端项目代码拆分记录
2019/03/15 Javascript
微信小程序中悬浮窗功能的实现代码
2019/08/02 Javascript
解决VUE双向绑定失效的问题
2019/10/29 Javascript
vue组件内部引入外部js文件的方法
2020/01/18 Javascript
[10:07]2014DOTA2国际邀请赛 实拍选手现场观战DK对阵Titan
2014/07/12 DOTA
Python格式化日期时间操作示例
2018/06/28 Python
python查看模块安装位置的方法
2018/10/16 Python
python+selenium实现自动抢票功能实例代码
2018/11/23 Python
Python3 中sorted() 函数的用法
2020/03/24 Python
Flask模板引擎Jinja2使用实例
2020/04/23 Python
JAVA的事件委托机制和垃圾回收机制
2014/09/07 面试题
C#如何进行LDAP用户校验
2012/11/21 面试题
一道输出判断型Java面试题
2014/10/01 面试题
预备党员2014全国两会学习心得体会
2014/03/10 职场文书
会计人员岗位职责
2014/03/19 职场文书
运动会宣传稿50字
2015/07/23 职场文书
《日月潭》教学反思
2016/02/20 职场文书
梳理总结Python开发中需要摒弃的18个坏习惯
2022/01/22 Python