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脚本在Appium库上对移动应用实现自动化测试
Apr 17 Python
Python随机数random模块使用指南
Sep 09 Python
python+opencv实现动态物体识别
Jan 09 Python
对python的文件内注释 help注释方法
May 23 Python
python通过Windows下远程控制Linux系统
Jun 20 Python
Python爬虫——爬取豆瓣电影Top250代码实例
Apr 17 Python
Python+selenium点击网页上指定坐标的实例
Jul 05 Python
使用Python自动生成HTML的方法示例
Aug 06 Python
Python3视频转字符动画的实例代码
Aug 29 Python
将tensorflow.Variable中的某些元素取出组成一个新的矩阵示例
Jan 04 Python
python3 logging日志封装实例
Apr 08 Python
Python机器学习实战之k-近邻算法的实现
Nov 27 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
怎样在UNIX系统下安装MySQL
2006/10/09 PHP
php中的注释、变量、数组、常量、函数应用介绍
2012/11/16 PHP
PHP_NETWORK_GETADDRESSES: GETADDRINFO FAILED问题解决办法
2014/05/04 PHP
PHP+FFMPEG实现将视频自动转码成H264标准Mp4文件
2014/09/24 PHP
PHP简单实现数字分页功能示例
2016/08/24 PHP
javascript的解析执行顺序在各个浏览器中的不同
2014/03/17 Javascript
jQueryUI中的datepicker使用方法详解
2016/05/25 Javascript
JS使用eval()动态创建变量的方法
2016/06/03 Javascript
jQuery 3.0中存在问题及解决办法
2016/07/15 Javascript
Angular.JS中的指令引用template与指令当做属性详解
2017/03/30 Javascript
使用Vue做一个简单的todo应用的三种方式的示例代码
2018/10/20 Javascript
Vue表单输入绑定的示例代码
2018/11/01 Javascript
JS中使用react-tooltip插件实现鼠标悬浮显示框
2019/05/15 Javascript
vue 指令和过滤器的基本使用(品牌管理案例)
2019/11/04 Javascript
解决vue单页面 回退页面 keeplive 缓存问题
2020/07/22 Javascript
解决Vue中使用keepAlive不缓存问题
2020/08/04 Javascript
梳理一下vue中的生命周期
2020/12/30 Vue.js
[01:12]DOTA2次级职业联赛 - Newbee.Y 战队宣传片
2014/12/01 DOTA
让python在hadoop上跑起来
2016/01/27 Python
python网络爬虫之如何伪装逃过反爬虫程序的方法
2017/11/23 Python
Python基础学习之函数方法实例详解
2019/06/18 Python
Django REST framework 分页的实现代码
2019/06/19 Python
python多进程下的生产者和消费者模型
2020/05/07 Python
python爬取代理IP并进行有效的IP测试实现
2020/10/09 Python
用python批量下载apk
2020/12/29 Python
基于Python的接口自动化unittest测试框架和ddt数据驱动详解
2021/01/27 Python
大四学年自我鉴定
2013/11/13 职场文书
施工资料员的岗位职责
2013/12/22 职场文书
我爱我校演讲稿
2014/05/21 职场文书
村长党的群众路线教育实践活动个人对照检查材料
2014/09/23 职场文书
群众路线教育查摆剖析材料
2014/10/10 职场文书
2015年度优秀员工自荐书
2015/03/06 职场文书
初中运动会前导词
2015/07/20 职场文书
Java 实战项目之家居购物商城系统详解流程
2021/11/11 Java/Android
Ruby处理YAML和json数据
2022/04/18 Ruby
JavaScript前端面试组合函数
2022/06/21 Javascript