装饰器的形成过程

假如你要写一个计算函数执行时间的函数,代码如下:

 import time

 def func1():
print('in func1') def timer(func):
def inner():
start = time.time()
func()
print(time.time() - start)
return inner func1 = timer(func1)
func1()

唯一碍眼的那句话就是还要在做一次赋值调用,你觉得碍眼,python的开发者也觉得碍眼,所以就为我们提供了一句语法来解决这个问题!

 import time
def 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 @timer
def func1(a):
print(a) func1(1) 装饰器——带参数的装饰器

其实装饰带参的函数并不是什么难事,但假如你有两个函数,需要传递的参数不一样呢?

 import time
def 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'))

现在参数的问题已经完美的解决了,可是如果你的函数是有返回值的呢?

 import time
def timer(func):
def inner(*args,**kwargs):
start = time.time()
re = func(*args,**kwargs)
print(time.time() - start)
return re
return inner @timer #==> func2 = timer(func2)
def func2(a):
print('in func2 and get a:%s'%(a))
return 'fun2 over' func2('aaaaaa')
print(func2('aaaaaa'))

刚刚那个装饰器已经非常完美了,但是正常我们情况下查看函数的一些信息的方法在此处都会失效

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

为了不让他们失效,我们还要在装饰器上加上一点来完善它:

 from functools import wraps

 def deco(func):
@wraps(func) #加在最内层函数正上方
def wrapper(*args,**kwargs):
return func(*args,**kwargs)
return wrapper @deco
def 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
# wraps版本
from functools import wraps def deco(func):
@wraps(func) #加在最内层函数正上方
def wrapper(*args,**kwargs):
return func(*args,**kwargs)
return wrapper

带参数的装饰器

可以实现函数是否执行

 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 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()

python三大神器之装饰器的更多相关文章

  1. python三大神器===》装饰器

    1.认识装饰器 如果你经常看我的博客,你已经学会了python的前两大‘神器’(迭代器,生成器),那么什么是装饰器呢?就如字面意义装饰器是对某个事物(通常指函数)进行装饰,让其在不修改任何内部代码的情 ...

  2. Python三大神器:装饰器,迭代器,生成器

    一.装饰器 由于一个函数能实现一种功能,现在想要在不改变其代码的情况下,让这个函数进化一下,即能保持原来的功能,还能有新的"技能",怎么办? 现已经存在一个自定义的函数func1, ...

  3. Python 三大神器

    Python 三大神器 Python 中有很多优秀的包,本文主要讲一下 pip, virtualenv, fabric 1. pip 用来包管理 文档:https://pip.pypa.io/en/l ...

  4. Python中利用函数装饰器实现备忘功能

    Python中利用函数装饰器实现备忘功能 这篇文章主要介绍了Python中利用函数装饰器实现备忘功能,同时还降到了利用装饰器来检查函数的递归.确保参数传递的正确,需要的朋友可以参考下   " ...

  5. python函数与方法装饰器

    之前用python简单写了一下斐波那契数列的递归实现(如下),发现运行速度很慢. def fib_direct(n): assert n > 0, 'invalid n' if n < 3 ...

  6. guxh的python笔记三:装饰器

    1,函数作用域 这种情况可以顺利执行: total = 0 def run(): print(total) 这种情况会报错: total = 0 def run(): print(total) tot ...

  7. python设计模式之内置装饰器使用(四)

    前言 python内部有许多内建装饰器,它们都有特别的功能,下面对其归纳一下. 系列文章 python设计模式之单例模式(一) python设计模式之常用创建模式总结(二) python设计模式之装饰 ...

  8. python 3.x 的装饰器笔记

    今天学到了python的装饰器,感觉这个东西还是稍微有些复杂,所以记录下来,方便以后的查找.虽然标题是python 3.x的装饰器,但是我也没有怎么用过python 2.x,感觉上应该是和python ...

  9. python 中多个装饰器的执行顺序

    python 中多个装饰器的执行顺序: def wrapper1(f1): print('in wrapper1') def inner1(*args,**kwargs): print('in inn ...

随机推荐

  1. SVN升级到1.8后 Upgrade working copy

    SVN升级到1.8后没法用了,不能提交,提示说要SVN Upgrade working copy, 但是半天在根目录和.svn所在文件夹上面右键都没有找到这个菜单. 坑爹的…… 最后找到解决办法是:重 ...

  2. angular2 ng build --prod 报错:Module not found: Error: Can't resolve './$$_gendir/app/app.module.ngfactory'

    调试页面 ng serve 正常 ng build 也正常 ng build --prod 异常:Module not found: Error: Can't resolve './$$_gendir ...

  3. [零基础学JAVA]Java SE基础部分-01. Java发展及JDK配置

    转自:http://redking.blog.51cto.com/27212/114976 重点要会以下两个方面: 1. 抽象类与接口 2. API==>类集 这是两个最重要部分,这两个部分理解 ...

  4. linux shell数据重定向

    标准输入 (stdin) :代码为 0 ,使用 < 或 << :标准输出 (stdout):代码为 1 ,使用 > 或 >> :标准错误输出(stderr):代码为 ...

  5. [由于远程方关闭传输流,身份验证失败]一次处理支付接口bug记录

    因公司系统升级,出现突然有些银行卡不能支付的情况,最开始排查发现是第三方平台接口返回有问题: 返回如下: 从11月7日下午开始一直联系第三方,第三方开始排查,一直说是数据格式有问题. 修改格式以后问题 ...

  6. iText中输出 中文

    iText中输出中文,有三种方式: 1.使用iTextAsian.jar中的字体    BaseFont.createFont("STSong-Light", "UniG ...

  7. Intellij IDEA设置注释作者名字

    方法一:File >> Settings >> Editor >>Code Style >> File and Code Templates>&g ...

  8. log4j框架logger的继承关系以及使用场景

    log4j框架logger的继承关系以及使用场景 log4j日志框架logger是存在继承关系的,我们一般都会在log4j.properties文件中定义log4j.rootLogger.其他所有lo ...

  9. BZOJ2654:tree(最小生成树,二分)

    Description 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树. 题目保证有解. Input 第一行V,E,need分别表示点数,边数和需要的白色 ...

  10. 如何设置活动监视器中的可见作业数能显示更长范围之内的作业(如何让bpdbjobs/Active Monitor显示更多作业信息)

    一.问题:     如何设置可以使得活动监视器中的可见作业数能显示更长范围之内的作业(即NBU软件不要自动删除活动监视器中短时间内(如8天)内的作业记录)? 二.解决方法:      默认情况下在Ac ...