博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python之装饰器
阅读量:7031 次
发布时间:2019-06-28

本文共 3229 字,大约阅读时间需要 10 分钟。

一,什么是装饰器?

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

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

二,装饰器的形成过程。

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

import timedef func1():    print('in func1')def timer(func):    def inner():        start = time.time()        func()        print(time.time() - start)    return innerfunc1 = timer(func1)func1()
装饰器 -- 简单版

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

import timedef timer(func):    def inner():        start = time.time()        func()        print(time.time() - start)    return inner@timer   #==> func1 = timer(func1)def func1():    print('in func1')func1()
装饰器 == 语法糖

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

def timer(func):    def inner(a):        start = time.time()        func(a)        print(time.time() - start)    return inner@timerdef func1(a):    print(a)func1(1)装饰器——带参数的装饰器
装饰器——带参数的装饰器
import timedef timer(func):    def inner(*args,**kwargs):        start = time.time()        re = func(*args,**kwargs)        print(time.time() - start)        return re    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))    return 'fun2 over'func1('aaaaaa','bbbbbb')print(func2('aaaaaa'))
装饰器 -- hold住所有参数的装饰器

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

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

如何解决呢?

from functools import wrapsdef deco(func):    @wraps(func) #加在最内层函数正上方    def wrapper(*args,**kwargs):        return func(*args,**kwargs)    return wrapper@decodef index():    '''哈哈哈哈'''    print('from index')print(index.__doc__)print(index.__name__)

三,开放封闭原则。

1.对扩展是开放的

    为什么要对扩展开放呢?

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

  2.对修改是封闭的

    为什么要对修改封闭呢?

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

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

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

def timer(func):    def inner(*args,**kwargs):        '''执行函数之前要做的'''        re = func(*args,**kwargs)        '''执行函数之后要做的'''        return re    return inner
装饰器的固定格式
from functools import wrapsdef deco(func):    @wraps(func) #加在最内层函数正上方    def wrapper(*args,**kwargs):        return func(*args,**kwargs)    return wrapper
装饰器的固定格式 -- wraps版

五,带参数的装饰器。

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

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

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

def outer(flag):    def timer(func):        def inner(*args,**kwargs):            if flag:                print('''执行函数之前要做的''')            re = func(*args,**kwargs)            if flag:                print('''执行函数之后要做的''')            return re        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 innerdef wrapper2(func):    def inner():        print('wrapper2 ,before func')        func()        print('wrapper2 ,after func')    return inner@wrapper2@wrapper1def f():    print('in f')f()
多个装饰器装饰一个函数

 

转载于:https://www.cnblogs.com/Big-Dinosaur/p/10268839.html

你可能感兴趣的文章
HDU3421 Max Sum II【序列处理】
查看>>
POJ NOI MATH-7653 地球人口承载力估计
查看>>
iOS UI高级之网络编程(HTTP协议)
查看>>
使用cocoaPods import导入时没有提示的解决办法
查看>>
iOS数据持久化存储之归档NSKeyedArchiver
查看>>
JavaScript面向对象
查看>>
Intellij修改模板代码
查看>>
2.页面布局示例笔记
查看>>
一些老游戏CPU 100%占用的解决方法
查看>>
f5基本介绍
查看>>
博前语
查看>>
Java SE核心之一:常用类,包装类,其他基本数据类型包装类。
查看>>
郑捷《机器学习算法原理与编程实践》学习笔记(第二章 中文文本分类(一))...
查看>>
python (ploit)
查看>>
Android 用achartengine 画折线图怎么显示不正确
查看>>
程序简单的测试与升级(暨实践第一次作业)
查看>>
信号处理
查看>>
【100题】第五十九题 用C++编写不能被继承的类
查看>>
轻描淡写
查看>>
mysql基本操作
查看>>