Python-装饰器

一.装饰器引入

def func():
    print('我是一句话')

1.如何输出上面这段程序的运行时间?

在没学习装饰器之前一定会通过修改原函数来实现程序附加功能。

import time
def func():
    start = time.time() # 记录开始时间
    print('这是一句话')
    end = time.time()   # 记录结束时间
    print(start - end)

2.但如果有成千上万的函数都需要加这个功能,又该怎么办?

下面就是一个最简单的装饰器

装饰器的作用:

不想修改函数的调用方式 但是还想在原来的函数前后添加功能

装饰器的原则:

原则:(开放封闭原则开放:对扩展是开放的; 封闭:对修改是封闭的;)

语法糖:@

"""
第一步:def timmer(f)并且def inner() 都是先声明不掉用
第二步:@timmer 即 func = timmer(func) 此时的 f = func
第三步:return inner 即 func = inner 注意:inner不加括号
第四步:调用func()即调用inner(),此刻的f已经是fun,因此就实现了功能附加

"""
import time
def timmer(f):
    def inner():
        start = time.time()
        f()
        end = time.time()
        print(end - start)
    return inner

@timmer    # @timmer 等价于 func = timmer(func)
def func():
    print('这是一句话')
func()

3.给装饰器加上返回值,并且带多个参数

"""
第一步:声明wrapper
第二步:@wrapper 即func = wrapper(func)
第三步:return inner 即 func = inner
第四步:调用func(a,b)即调用inner(*args, **kwargs),并传入参数a,b
第五步:ret = f(*args, **kwargs) ret = ‘哈哈哈’ 并return ret
"""

def wrapper(f):                            1
    def inner(*args, **kwargs):            3(声明)
        ret = f(*args, **kwargs)           6
        return ret                         8           
    return inner                           4

@wrapper #语法糖 func = wrapper(func)       2
def func(a,b):                             7
    print('这是一个被装饰的函数',a,b)
    return '哈哈哈'
func()                                     5

4.装饰器的固定模式形成

def wrappr(f):#f为被装饰函数
    def inner(*args,**kwargs): #*args,**kwargs万能参数
        ret = f(*args,**kwargs)
        return ret
    return inner
    
@wrapper #语法糖

二.装饰器进阶

1.带参数的装饰器

如果今天一万个函数需要使用装饰器,明天又不需要装饰器,后天又需要装饰器,该怎么办?

不能删了加,加了再删吧,因此引出了才参数的装饰器、

原理:在装饰器外再加在加一层装饰器 如:def timmer(func)外面加一层timmer_out(flag),然后在执行inner的通过判断flag的值来决定是否要附加功能。此时的语法糖也有所改变,原先是@timmer,加一层装饰器之后变成了@timmer_out(FLAG),其中FLAG为全局变量,@timmer_out(FLAG) 分为两步执行:第一步:timmer_out(FLAG) ,然后@接受返回值timmer,形成@timmer,而后执行步骤与不带参数的装饰器一样

带参数的装饰器主要目的是传入FLAG

import time

FLAG = False


def timmer_out(flag):
    def timmer(func):
        def inner(*args, **kwargs):
            if flag:
                start = time.time()
                ret = func(*args, **kwargs)
                end = time.time()
                print(start - end)
                return ret
            else:
                ret = func(*args, **kwargs)
                return ret

        return inner

    return timmer


# timmer = timmer_out(FLAG)
@timmer_out(FLAG)
def wahaha():
    time.sleep(0.1)
    print('hahahaha')


@timmer_out(FLAGE)
def erguotou():
    time.sleep(0.1)
    print('ttttt')

2.多个装饰器修饰一个函数(数字为执行步骤)

def wrapper1(func):                           1
    def inner1():                             4
        print('wrapper1,before func')         15
        func()                                16
        print('wrapper1,after func')          18

    return inner1                             5


def wrapper2(func):                           2
    def inner2():                             8
        print('wrapper2,before func')         13
        func()                                14
        print('wrapper2,after func')          19

    return inner2                             9


@wrapper2                                     7:f = wrapper2(inner) 10:f = inner2
@wrapper1                                     3:f = wrapper(f)  6:f=inner1
def f():
    print('in f')                             17


f()                                           11:inner2()

输出顺序如下:

三.其他

def timmer(f):  # 装饰器函数
    def inner(*args, **kwargs):
        '''
        ******inner******
        '''
        start = time.time()
        ret = f(*args, **kwargs)  # 被装饰的函数
        end = time.time()
        print(end - start)
        return ret

    return inner


@timmer
def func(a, b):
    """
    ******func******
    """
    print('大家好', a, b)

print(func.__name__)
print(func.__doc__)

输出结果:

可以发现装饰器装饰过的函数,用__name__以及__doc__方法输出的函数名以及注视都变成了inner,而非原函数的名字和注释

解决方法:

通过加入:

from functools import wraps

@wraps(f)

from functools import wraps
def timmer(f):  # 装饰器函数
    @wraps(f)
    def inner(*args, **kwargs):
        '''
        ******inner******
        '''
        start = time.time()
        ret = f(*args, **kwargs)  # 被装饰的函数
        end = time.time()
        print(end - start)
        return ret

    return inner


@timmer
def func(a, b):
    """
    ******func******
    """
    print('大家好', a, b)

print(func.__name__)
print(func.__doc__)

输出结果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值