概述

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

我们要需要一个能测试函数运行时间的decorator,可以定义如下:

def timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
res = func(*args, **kwargs)
end_time = time.time()
print("Run time is: %s" % (end_time - start_time))
return res
return wrapper

因为它是一个decorator,所以接受一个函数作为参数,并返回一个函数。我们要借助Python的@语法,把decorator置于函数的定义处:

@timer
def fun():
time.sleep(1)
print("This is a test")
return "OK"

运行结果就是:

This is a test
Run time is: 1.0000572204589844
OK

把@timer放在fun()处就相当于执行了语句:

fun = timer(fun)

如果decorator本身需要传入参数,那就需要编写一个返回decorator的高阶函数,比如加上名字:

def timer(name):
def decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
res = func(*args, **kwargs)
end_time = time.time()
print("Name is: %s ; Run time is: %s" % (name, (end_time - start_time)))
return res
return wrapper
return decorator

调用及结果显示如下:

@timer("Lance#")
def fun():
time.sleep(1)
print("This is a test")
return "OK"
This is a test
Name is: Lance# ; Run time is: 1.0000572204589844
OK

和两层嵌套的decorator相比,三层嵌套的效果是这样的:

fun = timer("Lance#")(fun)

因为函数也是对象,它也有__name__等属性。

在未加装饰器之前的fun()函数,调用 fun的__name__属性结果是 'fun',但经过decorator装饰之后的函数,它们的__name__已经从原来的'fun'变成了'wrapper'

所以,需要把原始函数的__name__等属性复制到wrapper()函数中,否则,有些依赖函数签名的代码执行就会出错。

Python内置的functools.wraps就可以完成这个任务,所以,一个完整的decorator的写法如下:

import functools

def timer(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
res = func(*args, **kwargs)
end_time = time.time()
print("Run time is: %s" % (end_time - start_time))
return res
return wrapper

整体代码如下:

__Author__ = "Lance#"

# -*- coding = utf-8 -*-

import time
import functools def timer(name):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
res = func(*args, **kwargs)
end_time = time.time()
print("Name is: %s ; Run time is: %s" % (name, (end_time - start_time)))
return res
return wrapper
return decorator @timer("Lance#")
def fun():
time.sleep(1)
print("This is a test")
return "OK" if __name__ == '__main__':
print(fun())

Python装饰器举例分析的更多相关文章

  1. [python 基础]python装饰器(一)添加functools获取原函数信息以及functools.partial分析

    python装饰器学习的时候有两点需要注意一下 1,被装饰器装饰的函数取其func.__name__和func.func_doc的时候得到的不是被修饰函数的相关信息而是装饰器wrapper函数的doc ...

  2. Python装饰器由浅入深

    装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们 ...

  3. python 装饰器 一篇就能讲清楚

    装饰器一直是我们学习python难以理解并且纠结的问题,想要弄明白装饰器,必须理解一下函数式编程概念,并且对python中函数调用语法中的特性有所了解,使用装饰器非常简单,但是写装饰器却很复杂.为了讲 ...

  4. Python装饰器探险

    关于python装饰器的理解和用法,推荐廖雪峰老师和这一篇博客以及知乎 以下代码均已手动敲过,看完本篇内容,包你装饰器小成! 装饰器实际上就是为了给某程序增添功能,但该程序已经上线或已经被使用,那么就 ...

  5. Python装饰器的通俗理解

    转载:http://blog.csdn.net/u013471155 在学习Python的过程中,我相信有很多人和我一样,对Python的装饰器一直觉得很困惑,我也是困惑了好久,并通过思考和查阅才能略 ...

  6. python装饰器(docorator)详解

    引言: 装饰器是python面向对象编程三大器之一,另外两个迭代器.生成器只是我现在还没有遇到必须使用的场景,等确实需要用到的时候,在补充资料:装饰器在某些场景真的是必要的,比如定义了一个类或者一个函 ...

  7. Python 装饰器学习心得

    最近打算重新开始记录自己的学习过程,于是就捡起被自己废弃了一年多的博客.这篇学习笔记主要是记录近来看的有关Python装饰器的东西. 0. 什么是装饰器? 本质上来说,装饰器其实就是一个特殊功能的函数 ...

  8. (一)Python装饰器的通俗理解

    在学习Python的过程中,我相信有很多人和我一样,对Python的装饰器一直觉得很困惑,我也是困惑了好久,并通过思考和查阅才能略有领悟,我希望以下的内容会对你有帮助,我也努力通过通俗的方式使得对Py ...

  9. Python 装饰器初探

    Python 装饰器初探 在谈及Python的时候,装饰器一直就是道绕不过去的坎.面试的时候,也经常会被问及装饰器的相关知识.总感觉自己的理解很浅显,不够深刻.是时候做出改变,对Python的装饰器做 ...

随机推荐

  1. sublime text 换行与不换行设置

    # 修改添加如下图右侧红框内容即可- 打开文件不换行

  2. SAS对数据变量的处理

    SAS对数据变量的处理 在使用DATA步基于已经存在的数据集生成新数据集时,可以指定在新数据集中不需要包含的变量而仅读取其他变量,或者指定仅需要在 新数据集中包含的变量.该功能可以通过DATA步中的S ...

  3. HashMap、HashTable

    HashMap 初始长度:1>>4   2^4=16 最大长度:1>>30   2^30 扩容时机:容量 >= 0.75f 扩容倍数:2倍 1.K可以为null 2.pu ...

  4. JAVA 8 主要新特性 ----------------(三)新功能Lambda表达式入门

    一.简述       Java为了扩充匿名方法在1.8中新追加的特性.本身Java之前的版本是没有匿名方法的,只有匿名对象. 二.使用        Java中使用匿名方法必须要对应接口中的一个抽象方 ...

  5. uasrt配置

    Universal Synchronous/Asynchronous Receiver/Transmitter 同步是指:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式.同步要有一个 ...

  6. 第四周Access的总结

    一.问;这节课你学到了什么知识? 答:这周我们学习了新的课程:表的建立和管理.这是Access最重要的一部份,需要我们认认真真学习!            字段是表最重要的信息,而数据类型是字段或表中 ...

  7. Centos yum 修改为阿里源以及常用的命令

    1.备份 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 2.下载新的CentOS-Base ...

  8. BASH 基本语法

    本节内容 1.  什么是shell script 2.  变量 3.  运算符 4.  流程控制 5.  函数 6.  计划任务 crontab 一  什么是shell script 将OS命令堆积到 ...

  9. 人脸识别准备 -- 基于raspberry pi 3b + movidius

    最近准备系统地学习一下深度学习和TensorFlow,就以人脸识别作为目的. 十年前我做过一些图像处理相关的项目和研究,涉及到图像检索.记得当时使用的是SIFT特征提取,该特征算子能很好地抵抗图像旋转 ...

  10. npm全局目录修改

    转载:http://www.qdfuns.com/notes/30749/0f66fcf5e62eed010f744d0d4adaa870.html 我之前安装npm时全是默认安装,模块全部安装在C盘 ...