python装饰器详解

一、什么是装饰器

装饰器就类似于你自己有好多衣服,换一套衣服就是新的样貌,但你始终是你,没有变。装饰器运用在函数中的话可以拓展你的代码,不需要你修改原来的函数和函数调用。装饰器分为函数装饰器和类装饰器。

二、为什么要用装饰器

先了解python中的函数也可作为函数的参数,如下:

def yisu():
    print("我是伊苏尔德")


def erde(name):
    print('进入erde函数')
    name()
    print('我叫伊苏尔德root,感谢大家关注我')


if __name__ == '__main__':
    func = yisu
    func()
    print('------------')
    erde(yisu)

那么我现在想知道他们的执行时间,修改代码如下:

import time


    def yisu():
        t = time.time()
        print("我是伊苏尔德")
        time.sleep(3)
        print("执行时间:", time.time() - t)


    def erde(name):
        t = time.time()
        print('进入erde函数')
        name()
        print('我叫伊苏尔德root,感谢大家关注我')
        print("执行时间:", time.time() - t)


    if __name__ == '__main__':
        func = yisu
        func()
        print('------------')
        erde(yisu)

此时我有一个新的函数,也想去计算执行时间,但是又会重复上面的代码,我们需要更方便一点,因此需要装饰器,让我们拓展一些原来函数没有的功能。

三、简单装饰器

import time


def yisu():
    print("我是伊苏尔德")
    time.sleep(2)


def count_time(func):
    def wrapper():
        t= time.time()
        func()
        print("执行时间为:", time.time() - t)

    return wrapper


if __name__ == '__main__':
    yisu = count_time(yisu) 
    yisu() 

count_time是一个装饰器,装饰器函数里面定义一个wrapper函数,把func函数当作参数传入,并返回wrapper函数。wrapper函数体就是要实现装饰器的内容。

四,装饰器的语法糖@

装饰器默认传入的参数就是被装饰的函数,加@就可以省略yisu = count_time(yisu) 

import time


def count_time(func):
    def wrapper():
        t = time.time()
        func()
        print("执行时间为:", time.time() - t)

    return wrapper


@count_time
def yisu():
    print("我是伊苏尔德")
    time.sleep(2)


if __name__ == '__main__':
    
    yisu()

五、装饰器传参

当我们被装饰的函数带参数时,就需要升级我们的装饰器了,将我们的装饰器改成如下,可以接受任何参数。

import time
 
 
def count_time(func):
    def wrapper(*args, **kwargs):
        t = time.time()
        func(*args, **kwargs)
        print("执行时间为:", time.time() - t)
 
    return wrapper
 
 
@count_time
def erde(name):
    print('进入erde函数')
    name()
    print('我叫伊苏尔德root,感谢大家关注我')

@count_time
def yisu():
    print("我是伊苏尔德")
    time.sleep(2)
 
 
if __name__ == '__main__':

    erde(yisu)

六、带参装饰器

装饰器函数也可以是函数,那么怎么写一个带参装饰器呢?如下:

import time


def count_time_args(msg=None):
    def count_time(func):
        def wrapper(*args, **kwargs):
            t = time.time()
            func(*args, **kwargs)
            print(f"[{msg}]执行时间为:", time.time() - t)

        return wrapper

    return count_time


@count_time_args(msg="yisu")
def fun():
    time.sleep(1)


if __name__ == '__main__':
    fun()

基于原来的count_time函数外部再包一层用于接收参数的count_time_args,接收回来的参数就可以直接在内部的函数里面调用了

七、类装饰器

就像函数装饰器一样,同类的类也可以有装饰器。当我们将类作为一个装饰器时,通过__init__()方法初始化类,通过__call__()方法调用真正的装饰方法。

import time


class YisuDecorator:
    def __init__(self, func):
        self.func = func
        print("执行类的__init__方法")

    def __call__(self, *args, **kwargs):
        print('进入__call__函数')
        t = time.time()
        self.func(*args, **kwargs)
        print("执行时间为:", time.time() - t)

@YisuDecorator
def yisu():
    print("我是伊苏尔德")
    time.sleep(2)

def python_erde_list():
    time.sleep(3)
    print("+++++++++++")
    
@YisuDecorator
def erde(name):
    print('进入erde函数')
    name()
    print('我是伊苏尔德')


if __name__ == '__main__':
    yisu()
    print('--------------')
    erde(python_erde_list)

当装饰器有参数的时候,__init__() 函数就不能传入func(func代表要装饰的函数)了,而func是在__call__函数调用的时候传入的。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值