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使用scrapy采集数据时为每个请求随机分配user-agent的方法
Apr 08 Python
python基于pygame实现响应游戏中事件的方法(附源码)
Nov 11 Python
详解Python中的array数组模块相关使用
Jul 05 Python
python验证码识别的实例详解
Sep 09 Python
机器学习10大经典算法详解
Dec 07 Python
windows下安装Python的XlsxWriter模块方法
May 03 Python
Python从单元素字典中获取key和value的实例
Dec 31 Python
python实现复制大量文件功能
Aug 31 Python
使用python+whoosh实现全文检索
Dec 09 Python
基于Python共轭梯度法与最速下降法之间的对比
Apr 02 Python
关于PyCharm安装后修改路径名称使其可重新打开的问题
Oct 20 Python
5行Python代码实现一键批量扣图
Jun 29 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
文章推荐系统(二)
2006/10/09 PHP
rrmdir php中递归删除目录及目录下的文件
2011/05/15 PHP
php实现监控varnish缓存服务器的状态
2014/12/30 PHP
PHP中preg_match函数正则匹配的字符串长度问题
2015/05/27 PHP
PHP实现的解汉诺塔问题算法示例
2018/08/06 PHP
PHP面向对象类型约束用法分析
2019/06/12 PHP
dojo学习第二天 ajax异步请求之绑定列表
2011/08/29 Javascript
js弹出层包含flash 不能关闭隐藏的2种处理方法
2013/06/17 Javascript
Javascript中call的两种用法实例
2013/12/13 Javascript
JSF中confirm弹出框的用法示例介绍
2014/01/07 Javascript
JS、DOM和JQuery之间的关系示例分析
2014/04/09 Javascript
JS模拟键盘打字效果的方法
2015/08/05 Javascript
jQuery左侧大图右侧小图焦点图幻灯切换代码分享
2015/08/19 Javascript
jquery实现加载进度条提示效果
2015/11/23 Javascript
js无提示关闭浏览器窗口的两种方法分析
2016/11/06 Javascript
Javascript下拉刷新的简单实现
2017/02/14 Javascript
jQuery实现字体颜色渐变效果的方法
2017/03/29 jQuery
vue+iview+less+echarts实战项目总结
2018/02/22 Javascript
vue同步父子组件和异步父子组件的生命周期顺序问题
2018/10/07 Javascript
小程序input数据双向绑定实现方法
2019/10/17 Javascript
[00:33]DOTA2上海特级锦标赛 CDEC战队宣传片
2016/03/04 DOTA
[03:49]2016完美“圣”典风云人物:AMS专访
2016/12/06 DOTA
[37:37]DAC2018 4.4 淘汰赛 Optic vs Mineski 第二场
2018/04/05 DOTA
python引入导入自定义模块和外部文件的实例
2017/07/24 Python
CSS实现定位元素居中的方法
2015/06/23 HTML / CSS
菲律宾最大的网上花店和礼品店:PhilFlower.com
2018/02/09 全球购物
工程地质勘察专业大学生求职信
2013/10/13 职场文书
四年的个人工作自我评价
2013/12/10 职场文书
房产买卖委托公证书
2014/04/04 职场文书
搞笑的获奖感言
2014/08/16 职场文书
党员领导干部民主生活会批评与自我批评发言
2014/09/28 职场文书
群众路线教育实践活动学习笔记
2014/11/05 职场文书
建党伟业电影观后感
2015/06/01 职场文书
毕业生政审意见范文
2015/06/04 职场文书
结婚纪念日感言
2015/08/01 职场文书
数学复习课教学反思
2016/02/18 职场文书