装饰器

普通装饰器

import time

#原始函数
def add():
    ret=0
    for i in range (3000000):
        ret = ret + i
    print(ret)


print("下面开始提需求------------------------------")

#需求: 记录一下执行的时间
def add():
    start_time=time.time()
    ret=0
    for i in range(3000000):
        ret = ret + i
    print(ret)
    end_time=time.time()
    print("spend %s" % (end_time-start_time))
add()
#虽然实现了要求 但是违反了开放封闭原则中的封闭原则

print("修改1---------------------------")

def show_time(func):
    start_time=time.time()
    func()
    end_time=time.time()
    print("spend %s" % (end_time - start_time))

def add():
    ret=0
    for i in range (3000000):
        ret = ret + i
    print(ret)

show_time(add)
# 没有改变原始函数,但是改变了调用方式.
# 违反了开放封闭原则中的开放原则
# 很容易想到可以改成  add()=show_time(add) 就不会改变调用方式
# 这就需要show_time(add)返回一个函数对象,***
# 而这个函数对象内则是核心业务函数:执行func() 和 装饰函数时间计算
# 修改如下:

print("修改2-----------------------")

def show_time(func):
    def inner():
        start_time=time.time()
        func()
        end_time=time.time()
        print("spend %s" % (end_time - start_time))
    return inner

def add():
    ret=0
    for i in range (3000000):
        ret = ret + i
    print(ret)

add=show_time(add)
add()
# 函数show_time就是装饰器,它把真正的业务方法func包裹在函数里面,
# 看起来像add被上下时间函数装饰了。
# 在这个例子中,函数进入和退出时 ,被称为一个横切面(Aspect),
# 这种编程方式被称为面向切面的编程(Aspect-Oriented Programming)。

print("修改3-----------------------")

# @符号是装饰器的语法糖,在定义函数的时候使用,避免再一次赋值操作,如下示例
def show_time(func):
    def inner():
        start_time=time.time()
        func()
        end_time=time.time()
        print("spend %s" % (end_time - start_time))
    return inner

@show_time   #add=show_time(add)
def add():
    ret=0
    for i in range (3000000):
        ret = ret + i
    print(ret)

@show_time
def bar():
    print("in the bar")
    time.sleep(2)

add()
bar()
#如上所示,这样我们就可以省去add = show_time(add)这一句了,直接调用add()即可得到想要的结果。
#这里需要注意:add=show_time(add)其实是把inner引用的对象引用给了add,
# 而inner里的变量func之所以可以用,就是因为inner是一个闭包函数。
#@show_time帮我们做的事情就是当我们执行业务逻辑add()时,
# 执行的代码由add函数代码块部分转到inner的代码块部分

print("带参数的被装饰函数-----------------------")

def show_time(func):
    def inner(a,b):   #注意要和add()函数中的形参个数对应
        start_time=time.time()
        func(a,b)
        end_time=time.time()
        print("spend %s" % (end_time - start_time))
    return inner

@show_time   #add=show_time(add)
def add(a,b):
    ret=0
    time.sleep(2)
    print(a+b)

add(2,4)

print("被装饰函数有返回值的情况-----------------------")

def show_time(func):
    def inner(a,b):   #注意要和add()函数中的形参个数对应
        start_time=time.time()
        ret= func(a,b)
        end_time=time.time()
        print("spend %s" % (end_time - start_time))
        return ret  # 若被装饰函数有返回值,则inner函数也一定要返回func(a,b)的结果

    return inner

@show_time   #add=show_time(add)
def add(a,b):
    ret=0
    time.sleep(2)
    print(a+b)

add(2,2)

装饰器带参数的情况

import time

flag=False
def outer(flag):
    def timer(func):
        def inner(*args,**kwargs):
            if flag:
                print(time.time())
                ret = func(*args,**kwargs) # 原来的函数
            else:
                ret = func(*args, **kwargs) # 原来的函数
            return ret
        return inner
    return timer


# @timer的时候   func1=timer(func1)  对应的是inner
@outer(True)   #func1=timer(func1)    inner
def func1():
    print("func1")

@outer(False)
def func2():
    print("func2")

func1()
func2()

多个装饰器修饰同一个函数

def wrapper1(func):
    def inner(*args, **kwargs):
        print('wrapper1 前')  # 2
        ret = func(*args, **kwargs)
        print('wrapper1 后')  # 4
        return ret
    return inner

def wrapper2(func):
    def inner(*args, **kwargs):
        print('wrapper2 前')  # 1
        ret = func(*args, **kwargs)
        print('wrapper2 后')  # 5
        return ret
    return inner

@wrapper2  # func1 = wrapper2(func1)  wrapper2.inner   func=wrapper1.inner
@wrapper1  # func1 = wrapper1(func1)  wrapper1.inner   func=func1
def func1():
    print('func1')  # 3
    return 'func1的返回值'

print(func1())  # 6

装饰器的修复技术

import time

from functools import wraps

def timer(func):
    @wraps(func)
    def inner():
        print(time.time())
        ret = func()  # 原来的函数
        return ret
    return inner


@timer  # func1 = timer(func1)
def func1():
    """
    func1 xxxx
    :return:
    """
    print('func1')
    return 'func1的返回值'

@timer  # func1 = timer(func1)
def func2():
    """
    func2 xxxx
    :return:
    """
    print('func2')
    return 'func2的返回值'

print(func1.__name__)
print(func2.__name__)
print(func2.__doc__)
原文地址:https://www.cnblogs.com/kenD/p/10066156.html