python之装饰器

Posted pankypan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python之装饰器相关的知识,希望对你有一定的参考价值。

---恢复内容开始---

python之装饰器

 

一,什么是装饰器?

装饰器本质上就是一个python闭包函数,他可以让其他函数在不需要做任何代码变动的前提下增加额外的功能装饰器的返回值也是一个函数对象。

装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景。

二,装饰器的形成过程。

现在我有一个需求,我想让你测试这个函数的执行时间,在不改变这个函数代码的情况下:

# import time
# def func1():
#     print(‘in func1‘)
#
# def timer(f):
#     def inner():
#         start_time = time.time()
#         f()
#         end_time = time.time()
#     return inner
# func1 = timer(func1)
# func1()

 

但是如果有多个函数,我都想让你测试他们的执行时间,你每次是不是都得func1 = timer(func1)?这样还是有点麻烦,因为这些函数的函数名可能是不相同,有func1,func2,graph,等等,所以更简单的方法,python给你提供了,那就是语法糖。

import time
def timer(f):
    def inner():
        start_time = time.time()
        f()
        end_time = time.time()
        print(end_time - start_time)
    return inner
@timer  #==  func1 = timer(func1)
def func1():
    print(in func1)
    time.sleep(0.5)

func1()

 

 刚刚我们讨论的装饰器都是装饰不带参数的函数,现在要装饰一个带参数的函数怎么办呢?

import time
def timer(f):
    def inner(a):
        start_time = time.time()
        f(a)
        end_time = time.time()
        print(end_time - start_time)
    return inner

@timer
def func1(a):
    print(a)
    time.sleep(0.2)

func1(9)
#装饰器——带参数的装饰器

 

import time
def timer(f):
    def inner(*args, **kwargs):  #参数聚合过程
        start_time = time.time()
        ret = f(*args, **kwargs)  #参数打散过程
        end_time = time.time()
        return ret
    return inner
@timer  # ==> func1 = timer(func1)
def func1(a, b):
    print(in func1)
@timer  # ==>  func2 = timer(func2)
def func2(a):
    print(in func2 and get a : %s % a)
@timer  # ==>   func3 = timer(func3)
def func3(a, b, c, d=3):
    print(a, b, c, d)
func1(1, 2)
func2(1)
func3(1, 2, 3, 5)

 

上面的装饰器已经非常完美了,但是有我们正常情况下查看函数信息的方法在此处都会失效:

def index():
    ‘‘‘这是一个主页信息‘‘‘
    print(form index)
print(index.__doc__)   #查看函数注释的方法
print(index.__name__)  #查看函数名的方法

 

如何解决呢?

from functools import wraps
def deco(f):
    @wraps(f) # 加在最内层函数正上方
    def wrapper(*args, **kwargs):
        return f(*args, **kwargs)
    return wrapper

@deco
def index():
    ‘‘‘嘻嘻哈哈‘‘‘
    print(from index)
print(index.__doc__)
print(index.__name__)

 

三,开放封闭原则。

1.对扩展是开放的

    为什么要对扩展开放呢?

    我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。

  2.对修改是封闭的

    为什么要对修改封闭呢?

    就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。

装饰器完美的遵循了这个开放封闭原则。

四,装饰器的主要功能和固定结构。

def timer(f):
    def inner(*args, **kwargs):
        ‘‘‘执行函数前要做的‘‘‘
        ret = f(*args, **kwargs)
        ‘‘‘执行函数之后要做的‘‘‘
        return ret
    return inner

 

from functools import wraps
def deco(f):
    @wraps(f)
    def wrapper(*args, **kwargs):
        return f(*args, **kwargs)
    return wrapper

 

五,带参数的装饰器。

假如你有成千上万个函数使用了一个装饰器,现在你想把这些装饰器都取消掉,你要怎么做?

一个一个的取消掉? 没日没夜忙活3天。。。

过两天你领导想通了,再让你加上。。。

def outer(flag):
    def timer(func):
        def inner(*args, **kwargs):
            if flag:
                print(‘‘‘执行函数之前要做的‘‘‘)
            ret = func(*args, **kwargs)
            if flag:
                print(‘‘‘执行函数之后要做的‘‘‘)
            return ret
        return inner
    return timer

@outer(False)
def func():
    print(111)

func()

 

六,多个装饰器装饰一个函数。

def wrapper1(func):
    def inner():
        print(wrapper1, before func)
        func()
        print(wrapper1, after func)
    return inner

def wrapper2(func):
    def inner():
        print(wrapper2, before func)
        func()
        print(wrapper2, after func)
    return inner

@wrapper2
@wrapper1
def f():
    print(in f)

f()
# wrapper2, before func
# wrapper1, before func
# in f
# wrapper1, after func
# wrapper2, after func

 

---恢复内容结束---

以上是关于python之装饰器的主要内容,如果未能解决你的问题,请参考以下文章

python之装饰器

python之装饰器

Python之装饰器

python之装饰器

我要学python之装饰器

Python之----装饰器