Python-装饰器

Python-装饰器,第1张

Python-装饰器 概述

在讲装饰器之前,要引入一个面向对象的核心原则——“开发封闭原则”。

开放封闭原则主要体现在两个方面:

  • 对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。
  • 对修改封闭,意味着类一旦设计完成,就可以独立完成其工作,而不要对类进行任何修改。

对于python中的已经完成的函数。我们应该不要对已有函数本身直接进行修改,但是我们仍然在需要新的功能时对其进行扩展。

装饰器的格式

在需要被装饰的函数上一行添加:@decorator_name

一个简单的装饰器

可以看到 函数 msg,只是简单输出了一句“hello world”。但是给它加上装饰器之后,再调用函数msg时,它从一个普普通通的“hello world”,变成了华丽(浮夸)的新函数。

def msg_plus(func):
    def wrapper():
        print('一位机智的少年走过来,对你说了一句:')
        func()
        print('然后,蹦蹦跳跳地走开了。')

    return wrapper


# 使用装饰器,对这个朴实无华的hello world进行装饰
@msg_plus
def msg():
    print("hello world")


msg()

----------
输出:
一位机智的少年走过来,对你说了一句:
hello world
然后,蹦蹦跳跳地走开了。

这里的msg调用装饰器msg_plus。其本质就相当于:msg = msg_plus(msg)

带参数的装饰器

传一个参数时

前面提到了,装饰器实际就是msg = msg_plus(msg),msg函数作为参数传给了msg_plus;返回值是wrapper。

则实际:表面上调用的msg(xx) ,背地里执行的 wrapper(xx)。

所以说,下面代码实际上msg定义的s1 和 wrapper定义的s2是一样的(s1 = s2,之所以这里写不一样是便于区分)。

def msg_plus(func):
    def wrapper(s2):
        print('一位机智的少年走过来,对你说了一句:')
        func(s2)
        print('然后,蹦蹦跳跳地走开了。')

    return wrapper


# 使用装饰器,对这个朴实无华的hello world进行装饰
@msg_plus
def msg(s1):
    print("说:{}".format(s1))


msg("其实我什么也不想说")

-----------
输出:
一位机智的少年走过来,对你说了一句:
说:其实我什么也不想说
然后,蹦蹦跳跳地走开了。

但我们大多数时候装饰器是给很多函数复用的,每个函数传的参数数量不一定相等。所以我们需要装饰器能接受可变长参数。所以装饰器中的wrapper函数的参数通常定义为*args,**kwargs(接收可变长的参数和可变长关键字参数)。如下:(两段代码实现的是一样的事,只是下面这个可接收可变长参数和可变长关键字参数)

def msg_plus(func):
    def wrapper(*args, **kwargs):
        print('一位机智的少年走过来,对你说了一句:')
        func(*args, **kwargs)
        print('然后,蹦蹦跳跳地走开了。')

    return wrapper


# 使用装饰器,对这个朴实无华的hello world进行装饰
@msg_plus
def msg(s1):
    print("说:{}".format(s1))


msg("其实我什么也不想说")

-----------
输出:
一位机智的少年走过来,对你说了一句:
说:其实我什么也不想说
然后,蹦蹦跳跳地走开了。

装饰器修饰有返回值的函数

这里装饰器里的返回值,可以跟原函数一样,也可以跟原函数不一样,根据实际需求确定。比如我这边的返回值,原函数中原本是没有返回值的。

def msg_plus(func):
    def wrapper(*args, **kwargs):
        print('一位机智的少年走过来,对你说了一句:')
        func(*args, **kwargs)
        print('然后,蹦蹦跳跳地走开了。')
        boy_msg = '叽里咕噜,叽里咕噜'
        return boy_msg

    return wrapper


# 使用装饰器,对这个朴实无华的hello world进行装饰
@msg_plus
def msg(s1):
    print("说:{}".format(s1))


result = msg("其实我什么也不想说")
print("他刚说什么?:", result)


-----------
输出:
一位机智的少年走过来,对你说了一句:
说:其实我什么也不想说
然后,蹦蹦跳跳地走开了。
他刚嘎说什么?: 叽里咕噜,叽里咕噜

带参数的装饰器

装饰器带参数,将开启套娃模式。以后用多了再补充吧~

装饰器使用场景
  1. 引入日志
  2. 函数执行时间统计
  3. 执行函数前预备处理
  4. 执行函数后清理功能
  5. 权限校验等场景
  6. 缓存

 

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5579603.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-14
下一篇 2022-12-14

发表评论

登录后才能评论

评论列表(0条)

保存