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中的CURL PycURL使用例子
Jun 01 Python
python实现各进制转换的总结大全
Jun 18 Python
Django原生sql也能使用Paginator分页的示例代码
Nov 15 Python
python 除法保留两位小数点的方法
Jul 16 Python
python 列表转为字典的两个小方法(小结)
Jun 28 Python
浅析Python 引号、注释、字符串
Jul 25 Python
pytorch索引查找 index_select的例子
Aug 18 Python
基于Python获取照片的GPS位置信息
Jan 20 Python
解决Python 异常TypeError: cannot concatenate 'str' and 'int' objects
Apr 08 Python
Python使用pycharm导入pymysql教程
Sep 16 Python
Python如何使用ConfigParser读取配置文件
Nov 12 Python
浅谈Python实现opencv之图片色素的数值运算和逻辑运算
Jun 23 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/08/27 PHP
JQuery获取元素文档大小、偏移和位置和滚动条位置的方法集合
2010/01/12 Javascript
JavaScript 小型打飞机游戏实现原理说明
2010/10/28 Javascript
让低版本浏览器支持input的placeholder属性(js方法)
2013/04/03 Javascript
浅析jquery ajax异步调用方法中不能给全局变量赋值的原因及解决方法
2014/01/10 Javascript
常用的jQuery前端技巧收集
2014/12/24 Javascript
jQuery中position()方法用法实例
2015/01/16 Javascript
JavaScript实现输入框(密码框)出现提示语
2016/01/12 Javascript
快速解决brew安装特定版本flow的问题
2018/05/17 Javascript
详解使用vue-admin-template的优化历程
2018/05/20 Javascript
jQuery实现获取当前鼠标位置并输出功能示例
2019/01/05 jQuery
JavaScript数组去重的方法总结【12种方法,号称史上最全】
2019/02/28 Javascript
vue响应式更新机制及不使用框架实现简单的数据双向绑定问题
2019/06/27 Javascript
基于vue--key值的特殊用处详解
2020/07/31 Javascript
[01:27]2014DOTA2展望TI 剑指西雅图IG战队专访
2014/06/30 DOTA
python encode和decode的妙用
2009/09/02 Python
python基础入门详解(文件输入/输出 内建类型 字典操作使用方法)
2013/12/08 Python
python基于xmlrpc实现二进制文件传输的方法
2015/06/02 Python
Python中内建函数的简单用法说明
2016/05/05 Python
用Python写脚本,实现完全备份和增量备份的示例
2018/04/29 Python
解决Pycharm中import时无法识别自己写的程序方法
2018/05/18 Python
Python HTML解析器BeautifulSoup用法实例详解【爬虫解析器】
2019/04/05 Python
django admin 自定义替换change页面模板的方法
2019/08/23 Python
Python greenlet和gevent使用代码示例解析
2020/04/01 Python
tensorflow使用CNN分析mnist手写体数字数据集
2020/06/17 Python
Python局部变量与全局变量区别原理解析
2020/07/14 Python
CSS3弹性盒模型开发笔记(一)
2016/04/26 HTML / CSS
HTML5头部标签的一些常用信息小结
2016/10/23 HTML / CSS
几道PHP的面试题
2012/05/19 面试题
《童年的发现》教学反思
2014/02/14 职场文书
寒假家长评语大全
2014/04/16 职场文书
学校献爱心活动总结
2014/07/08 职场文书
助人为乐好少年事迹材料
2014/08/18 职场文书
党员干部四风问题整改措施思想汇报
2014/10/12 职场文书
党的群众路线教育实践活动组织生活会发言材料
2014/10/17 职场文书
2015年反洗钱工作总结
2015/04/25 职场文书