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中文问题解决方法(总结了多位前人经验,初学者必看)
Mar 13 Python
详解Python中contextlib上下文管理模块的用法
Jun 28 Python
Python实现一个简单的验证码程序
Nov 03 Python
Python使用flask框架操作sqlite3的两种方式
Jan 31 Python
python merge、concat合并数据集的实例讲解
Apr 12 Python
Python3实现爬取指定百度贴吧页面并保存页面数据生成本地文档的方法
Apr 22 Python
Python实现二维曲线拟合的方法
Dec 29 Python
python实现接口并发测试脚本
Jun 25 Python
python爬虫 批量下载zabbix文档代码实例
Aug 21 Python
Python random模块制作简易的四位数验证码
Feb 01 Python
Opencv图像处理:如何判断图片里某个颜色值占的比例
Jun 03 Python
Python实现Word文档转换Markdown的示例
Dec 22 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
PHP反转字符串函数strrev()函数的用法
2012/02/04 PHP
php切割页面div内容的实现代码分享
2012/07/31 PHP
PHP生成图像验证码的方法小结(2种方法)
2016/07/18 PHP
PHP结合Ueditor并修改图片上传路径
2016/10/16 PHP
关于PHP求解三数之和问题详析
2020/11/09 PHP
JavaScript 模仿vbs中的 DateAdd() 函数的代码
2007/08/13 Javascript
JQuery的Alert消息框插件使用介绍
2010/10/09 Javascript
JS动态添加与删除select中的Option对象(示例代码)
2013/12/25 Javascript
提交按钮的name='submit'引起的js失效问题及原因
2015/02/25 Javascript
js 判断所选时间(或者当前时间)是否在某一时间段的实现代码
2015/09/05 Javascript
js实现人民币大写金额形式转换
2016/04/27 Javascript
JavaScript数组实现数据结构中的队列与堆栈
2016/05/26 Javascript
利用Angularjs和bootstrap实现购物车功能
2016/08/31 Javascript
使用JS代码实现点击按钮下载文件
2016/11/12 Javascript
使用Math.max,Math.min获取数组中的最值实例
2017/04/25 Javascript
Ionic3实现图片瀑布流布局
2017/08/09 Javascript
vue中使用ueditor富文本编辑器
2018/02/08 Javascript
详解VUE单页应用骨架屏方案
2019/01/17 Javascript
JS获取当前时间的年月日时分秒及时间的格式化的方法
2019/12/18 Javascript
javascript实现页面的实时时钟显示示例
2020/08/06 Javascript
vue+elementUI动态增加表单项并添加验证的代码详解
2020/12/17 Vue.js
使用C#配合ArcGIS Engine进行地理信息系统开发
2016/02/19 Python
Python中的上下文管理器和with语句的使用
2018/04/17 Python
python 多线程重启方法
2019/02/18 Python
python2.7的flask框架之引用js&css等静态文件的实现方法
2019/08/22 Python
Python 用三行代码提取PDF表格数据
2019/10/13 Python
python 装饰器重要在哪
2021/02/14 Python
css3的@media属性实现页面响应式布局示例代码
2014/02/10 HTML / CSS
台湾前三大B2C购物网站:MOMO购物网
2017/04/27 全球购物
美国知名生活购物网站:Goop
2017/11/03 全球购物
RetroStage德国:复古服装
2019/02/03 全球购物
动态密码技术
2012/10/18 面试题
销售助理岗位职责
2014/02/21 职场文书
《月球之谜》教学反思
2016/02/20 职场文书
nginx限制并发连接请求数的方法
2021/04/01 Servers