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利用QQ邮箱发送邮件的实现方法(分享)
Jun 09 Python
机器学习python实战之决策树
Nov 01 Python
Python将多个excel文件合并为一个文件
Jan 03 Python
手把手教你用python抢票回家过年(代码简单)
Jan 21 Python
Ubuntu下使用python读取doc和docx文档的内容方法
May 08 Python
Django框架视图层URL映射与反向解析实例分析
Jul 29 Python
pytorch 实现将自己的图片数据处理成可以训练的图片类型
Jan 08 Python
Python3读写Excel文件(使用xlrd,xlsxwriter,openpyxl3种方式读写实例与优劣)
Feb 13 Python
pip安装提示Twisted错误问题(Python3.6.4安装Twisted错误)
May 09 Python
Python使用OpenPyXL处理Excel表格
Jul 02 Python
Python实现像awk一样分割字符串
Sep 15 Python
5分钟快速掌握Python定时任务框架的实现
Jan 26 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 printf输出格式使用说明
2010/12/05 PHP
php之Smarty模板使用方法示例详解
2014/07/08 PHP
PHP getallheaders无法获取自定义头(headers)的问题
2016/03/23 PHP
laravel 5.4 + vue + vux + element的环境搭配过程介绍
2018/04/26 PHP
jQuery 过滤方法filter()选择具有特殊属性的元素
2014/06/15 Javascript
Javascript中的五种数据类型详解
2014/12/26 Javascript
JS实现登录页面记住密码和enter键登录方法推荐
2016/05/10 Javascript
gulp-htmlmin压缩html的gulp插件实例代码
2016/06/06 Javascript
基于angular中的重要指令详解($eval,$parse和$compile)
2016/10/21 Javascript
Nodejs实现短信验证码功能
2017/02/09 NodeJs
浅谈Express异步进化史
2017/09/09 Javascript
JS原型继承四步曲及原型继承图一览
2017/11/28 Javascript
Vue cli 引入第三方JS和CSS的常用方法分享
2018/01/20 Javascript
vue实现组件之间传值功能示例
2018/07/13 Javascript
JavaScript函数节流和函数去抖知识点学习
2018/07/31 Javascript
Element中的Cascader(级联列表)动态加载省\市\区数据的方法
2019/03/27 Javascript
JS中的防抖与节流及作用详解
2019/04/01 Javascript
python模拟登录百度贴吧(百度贴吧登录)实例
2013/12/18 Python
python爬虫入门教程之糗百图片爬虫代码分享
2014/09/02 Python
python利用拉链法实现字典方法示例
2017/03/25 Python
Django中使用Celery的方法示例
2018/11/29 Python
Python 3.10 的首个 PEP 诞生,内置类型 zip() 迎来新特性(推荐)
2020/07/03 Python
使用canvas压缩图片大小的方法示例
2019/08/02 HTML / CSS
Marc O’Polo俄罗斯官方在线商店:德国高端时尚品牌
2019/12/26 全球购物
介绍一下Linux文件的记录形式
2012/04/18 面试题
UNIX文件名称有什么规定
2013/03/25 面试题
软件工程师岗位职责
2013/11/16 职场文书
小学生演讲稿
2014/01/12 职场文书
护士毕业生自我鉴定
2014/02/08 职场文书
技术总监管理职责范本
2014/03/06 职场文书
中秋寄语大全
2014/04/11 职场文书
计算机实训报告范文
2014/11/05 职场文书
品德与社会教学反思
2016/02/24 职场文书
成功的商业计划书这样写才最靠谱
2019/07/12 职场文书
MySQL系列之十 MySQL事务隔离实现并发控制
2021/07/02 MySQL
winserver2019安装软件一直卡在应用程序正在为首次使用做准备
2022/06/10 Servers