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下使用Psyco模块优化运行速度
Apr 05 Python
python中input()与raw_input()的区别分析
Feb 27 Python
WINDOWS 同时安装 python2 python3 后 pip 错误的解决方法
Mar 16 Python
Python 在字符串中加入变量的实例讲解
May 02 Python
numpy中的delete删除数组整行和整列的实例
May 09 Python
Django 浅谈根据配置生成SQL语句的问题
May 29 Python
numpy linalg模块的具体使用方法
May 26 Python
python二进制读写及特殊码同步实现详解
Oct 11 Python
tensorflow2.0与tensorflow1.0的性能区别介绍
Feb 07 Python
Pytorch 扩展Tensor维度、压缩Tensor维度的方法
Sep 09 Python
Windows安装Anaconda3的方法及使用过程详解
Jun 11 Python
python中super()函数的理解与基本使用
Aug 30 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 ADODB使用方法集锦
2008/03/25 PHP
DedeCMS dede_channeltype表字段注释
2010/04/07 PHP
WordPress中的shortcode短代码功能使用详解
2016/05/17 PHP
php和redis实现秒杀活动的流程
2019/07/17 PHP
laravel 解决Validator使用中出现的问题
2019/10/25 PHP
建议大家看下JavaScript重要知识更新
2007/07/08 Javascript
jQuery获取当前对象标签名称的方法
2014/02/07 Javascript
Nodejs实现的一个简单udp广播服务器、客户端
2014/09/25 NodeJs
JS实现复制内容到剪贴板功能兼容所有浏览器(推荐)
2016/06/17 Javascript
jQuery实现给input绑定回车事件的方法
2017/02/09 Javascript
用 js 的 selection range 操作选择区域内容和图片
2017/04/18 Javascript
JS触摸与手势事件详解
2017/05/09 Javascript
js链表操作(实例讲解)
2017/08/29 Javascript
angular动态表单制作
2018/02/23 Javascript
Vue中的混入的使用(vue mixins)
2018/06/01 Javascript
layui checkbox默认选中,获取选中值,清空所有选中项的例子
2019/09/02 Javascript
ligerUI的ligerDialog关闭刷新的方法
2019/09/27 Javascript
关于vue表单提交防双/多击的例子
2019/10/31 Javascript
javascript使用canvas实现饼状图效果
2020/09/08 Javascript
如何封装Vue Element的table表格组件
2021/02/06 Vue.js
Python解析网页源代码中的115网盘链接实例
2014/09/30 Python
Python爬豆瓣电影实例
2018/02/23 Python
python实现定时提取实时日志程序
2018/06/22 Python
python3在同一行内输入n个数并用列表保存的例子
2019/07/20 Python
PyTorch中torch.tensor与torch.Tensor的区别详解
2020/05/18 Python
详解Sticky Footer 绝对底部的两种套路
2017/11/03 HTML / CSS
四方通行旅游网:台湾订房、出国旅游
2017/09/20 全球购物
上海某公司.net方向笔试题
2014/09/14 面试题
Unix如何在一行中运行多个命令
2015/05/29 面试题
中专自我鉴定范文
2013/10/16 职场文书
销售文员的岗位职责
2013/11/20 职场文书
机械设备与数控技术专业求职信
2014/08/10 职场文书
综合素质评价个性与发展自我评价
2015/03/06 职场文书
python使用pymysql模块操作MySQL
2021/06/16 Python
MongoDB安装使用并实现Python操作数据库
2021/06/28 MongoDB
光之国的四大叛徒:第一贝利亚导致宇宙毁灭,赛文奥特曼在榜
2022/03/18 日漫