python 装饰器

python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用

python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能。装饰器可能只看表面意思不太好理解,

结合例子可能更好理解一点

import time

def func():
    print("hello")
    time.sleep(2)
    print("world")

 if __name__=="__main__":
     func

如果需要分析函数性能,统计计算时间,最简单的办法如下:

import time

def func2():
    start = time.time()
    print("hello")
    time.sleep(2)
    print("world")
    end = time.time()
    print("time is {}".format(end-start))

这是最简单的逻辑,直接改没啥问题,如果比较复杂呢,你敢直接改核心逻辑吗,你不怕原来正常的逻辑改出bug吗,怎么办,那就分离呗:

import time

def func():
    print("hello")
    time.sleep(2)
    print("world")


def deco(func):
    start = time.time()
    func()
    end = time.time()
    print("time is {}".format(end - start))


if __name__ == '__main__':
    #func
    deco(func)

但是,这样的做法也有一个问题,就是n多个func,如果都要添加这个功能,就得执行n多deco()函数,是不是显得有些麻烦?

下面做一些改动,来避免计时功能对func函数调用代码的影响:

import time

def deco(func):
    def wrapper():
        start = time.time()
        func()
        end = time.time()
        print("time is {}".format(end - start))
    return wrapper()

@deco
def func():
    print("hello")
    time.sleep(2)
    print("world")


if __name__ == '__main__':
    func

现在是不是好了,既不影响原来的业务逻辑,又能拓展我们想要的性能分析。

这里只是最原始的装饰器,如果需要参数,只需要少许修改就可以:

import time

def deco(func):
    def wrapper(*args,**kwargs):
        start = time.time()
        print("args:",args)
        print("kwargs:",kwargs)
        func(*args,**kwargs)
        end = time.time()
        print("time is {}".format(end - start))
    return wrapper

@deco
def func(*args,**kwargs):
    print("hello")
    time.sleep(2)
    print("world")

if __name__ == '__main__':
    func(1,2,a=3,b=4)

看现在是不是越来越强大了,对源代码基本不会有侵入。

你可能会想,能不能支持多个装饰器,当然可以:

import time


def deco(func):
    def wrapper(*args,**kwargs):
        start = time.time()
        print("args:",args)
        print("kwargs:",kwargs)
        func(*args,**kwargs)
        end = time.time()
        print("time is {}".format(end - start))
    return wrapper

def deco2(func):
    def wrapper(*args,**kwargs):
        start = time.time()
        print("args2:",args)
        print("kwargs2:",kwargs)
        func(*args,**kwargs)
        end = time.time()
        print("time2 is {}".format(end - start))
    return wrapper

@deco
@deco2
def func(*args, **kwargs):
    print("hello")
    time.sleep(2)
    print("world")


if __name__ == '__main__':
    func(1, 2, a=3, b=4)
    #执行顺序=deco(deco2(func(1, 2, a=3, b=4)))

而且,装饰器本身也可以支持参数:

def deco(arg=True):
    if arg:
        def _deco(func):
            def wrapper(*args, **kwargs):
                start = time.time()
                print("args:", args)
                print("kwargs:", kwargs)
                func(*args, **kwargs)
                end = time.time()
                print("time is {}".format(end - start))

            return wrapper
    else:
        def _deco(func):
            return func

    return _deco

@deco(True)
def func(*args, **kwargs):
    print("hello")
    time.sleep(2)
    print("world")


if __name__ == '__main__':
    func(1, 2, a=3, b=4)

可以看到,如果装饰器本身需要支持参数,那么装饰器就需要多一层的内嵌函数,这时候func(1,2,a=3,b=4)=deco(True)(func(1,2,a=3,b=4)).

所以有了装饰器,就可以提取大量函数中与本身功能无关的类似代码,从而达到代码重用的目的,有很多经典使用场景,像插入日志、性能分析、事务处理等等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值