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 如何快速找出两个电子表中数据的差异
May 26 Python
使用python和Django完成博客数据库的迁移方法
Jan 05 Python
Python matplotlib 画图窗口显示到gui或者控制台的实例
May 24 Python
Python基于多线程实现抓取数据存入数据库的方法
Jun 22 Python
基于python实现简单日历
Jul 28 Python
Python Requests库基本用法示例
Aug 20 Python
python字典的setdefault的巧妙用法
Aug 07 Python
Python3 hashlib密码散列算法原理详解
Mar 30 Python
Python多个装饰器的调用顺序实例解析
May 22 Python
opencv 图像轮廓的实现示例
Jul 08 Python
详解Python中第三方库Faker
Sep 25 Python
详解利用python识别图片中的条码(pyzbar)及条码图片矫正和增强
Nov 17 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/08 PHP
linux实现php定时执行cron任务详解
2013/12/24 PHP
对于ThinkPHP框架早期版本的一个SQL注入漏洞详细分析
2014/07/04 PHP
CodeIgniter实现更改view文件夹路径的方法
2014/07/04 PHP
Yii2基于Ajax自动获取表单数据的方法
2016/08/10 PHP
php中的抽象方法和抽象类
2017/02/14 PHP
解决php用mysql方式连接数据库出现Deprecated报错问题
2019/12/25 PHP
javascript 屏蔽鼠标键盘的几段代码
2008/01/02 Javascript
广告切换效果(缓动切换)
2009/05/27 Javascript
疯狂Jquery第一天(Jquery学习笔记)
2012/05/11 Javascript
javascript中普通函数的使用介绍
2013/12/19 Javascript
extjs 时间范围选择自动判断的实现代码
2014/06/24 Javascript
jQuery前端框架easyui使用Dialog时bug处理
2014/12/05 Javascript
javascript常见数据验证插件大全
2015/08/03 Javascript
Bootstrap~多级导航(级联导航)的实现效果【附代码】
2016/03/08 Javascript
JavaScript的模块化开发框架Sea.js上手指南
2016/05/12 Javascript
修改jquery中dialog的title属性方法(推荐)
2016/08/26 Javascript
AngularJS解决ng界面长表达式(ui-set)的方法分析
2016/11/07 Javascript
JavaScript登录记住密码操作(超简单代码)
2017/03/22 Javascript
addEventListener()与removeEventListener()解析
2017/04/20 Javascript
vue 使用鼠标滚动加载数据的例子
2019/10/31 Javascript
JavaScript使用canvas绘制随机验证码
2020/02/17 Javascript
JS Thunk 函数的含义和用法实例总结
2020/04/08 Javascript
vue 实现根据data中的属性值来设置不同的样式
2020/08/04 Javascript
OpenLayers3实现地图显示功能
2020/09/25 Javascript
Python 创建空的list,以及append用法讲解
2018/05/04 Python
python bmp转换为jpg 并删除原图的方法
2018/10/25 Python
Python对excel文档的操作方法详解
2018/12/10 Python
python 函数的缺省参数使用注意事项分析
2019/09/17 Python
浅谈Django中的QueryDict元素为数组的坑
2020/03/31 Python
python爬虫工具例举说明
2020/11/30 Python
python 基于selenium实现鼠标拖拽功能
2020/12/24 Python
应用化学专业职业生涯规划书
2013/12/31 职场文书
计算机实训报告总结
2014/11/05 职场文书
2015夏季作息时间调整通知
2015/04/24 职场文书
授权协议书范本(3篇)
2019/10/15 职场文书