Python装饰器举例分析
概述
装饰器本质上是一个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装饰器举例分析的更多相关文章
- [python 基础]python装饰器(一)添加functools获取原函数信息以及functools.partial分析
python装饰器学习的时候有两点需要注意一下 1,被装饰器装饰的函数取其func.__name__和func.func_doc的时候得到的不是被修饰函数的相关信息而是装饰器wrapper函数的doc ...
- Python装饰器由浅入深
装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们 ...
- python 装饰器 一篇就能讲清楚
装饰器一直是我们学习python难以理解并且纠结的问题,想要弄明白装饰器,必须理解一下函数式编程概念,并且对python中函数调用语法中的特性有所了解,使用装饰器非常简单,但是写装饰器却很复杂.为了讲 ...
- Python装饰器探险
关于python装饰器的理解和用法,推荐廖雪峰老师和这一篇博客以及知乎 以下代码均已手动敲过,看完本篇内容,包你装饰器小成! 装饰器实际上就是为了给某程序增添功能,但该程序已经上线或已经被使用,那么就 ...
- Python装饰器的通俗理解
转载:http://blog.csdn.net/u013471155 在学习Python的过程中,我相信有很多人和我一样,对Python的装饰器一直觉得很困惑,我也是困惑了好久,并通过思考和查阅才能略 ...
- python装饰器(docorator)详解
引言: 装饰器是python面向对象编程三大器之一,另外两个迭代器.生成器只是我现在还没有遇到必须使用的场景,等确实需要用到的时候,在补充资料:装饰器在某些场景真的是必要的,比如定义了一个类或者一个函 ...
- Python 装饰器学习心得
最近打算重新开始记录自己的学习过程,于是就捡起被自己废弃了一年多的博客.这篇学习笔记主要是记录近来看的有关Python装饰器的东西. 0. 什么是装饰器? 本质上来说,装饰器其实就是一个特殊功能的函数 ...
- (一)Python装饰器的通俗理解
在学习Python的过程中,我相信有很多人和我一样,对Python的装饰器一直觉得很困惑,我也是困惑了好久,并通过思考和查阅才能略有领悟,我希望以下的内容会对你有帮助,我也努力通过通俗的方式使得对Py ...
- Python 装饰器初探
Python 装饰器初探 在谈及Python的时候,装饰器一直就是道绕不过去的坎.面试的时候,也经常会被问及装饰器的相关知识.总感觉自己的理解很浅显,不够深刻.是时候做出改变,对Python的装饰器做 ...
随机推荐
- 《Linux就该这么学》第五天课程
今天我很迷茫! 一下是一些命令的整合 原创地址:https://www.linuxprobe.com/chapter-04.html 下面是Linux系统中最重要的10个环境变量 变量名称 作用 HO ...
- 学以致用二十四-----shell脚本中的列表及space
1.接触列表的概念是在pyhon中,殊不知在shell中也是有列表的. 如: 结果 列表的下标和python中一样,也是以0开头 注意 list 和list2 的区别 一个是用括号括起来,一个是用 ...
- VIP之Switch
Switch II 最大能连接12路输入与12路输出 不能合并数据数 每个输入可以驱动多个输出 每个输出只能被一个输入驱动 当输入没有连接到输出时,可以禁止掉 每个被禁止的输入可以设置成停止或者消耗模 ...
- 如何将uniurlframe中html调用delphi的函数
uniGUI总群中台中cmj朋友为我们总结了如下内容,对于利用delphi+uniGUI开发应用,可以说是精品,必须掌握. 一句话,如何在html与delphi间交互代码,是最好的答案. [Clien ...
- Android-普通变量与普通方法内存图
描述Worker对象: package android.java.oop11; // 描述Worker public class Worker { public String name; public ...
- Hessian 使用例子
一.协议包(数据对象需要实现序列化接口,可以用于服务端接口.客户端调用服务之用) /** * */ package com.junge.demo.protocol.model; import java ...
- Zhu-Takaoka Two-dimensional Pattern Matching
Two dimensional pattern matching. Details may be added later.... Corresponding more work can be foun ...
- Python 绝技 —— UDP 服务器与客户端
i春秋作家:wasrehpic 0x00 前言 在上一篇文章「Python 绝技 —— TCP 服务器与客户端」中,介绍了传输层的核心协议 TCP ,并运用 Python 脚本的 socket 模块演 ...
- elasticsearch学习之根据发布时间设置衰减函数
衰减函数decay functionion 高斯衰减 GET _search { "_source": ["title","release_date& ...
- linux常用的BootLoader U-boot的前世今生
U-Boot,全称 Universal Boot Loader,是遵循GPL条款的开放源码项目.U-Boot的作用是系统引导. U-Boot从FADSROM.8xxROM.PPCBOOT逐步发展演化而 ...