内容简介:这篇文章主要介绍了Python装饰器(decorator)定义与用法,结合具体实例形式详细分析了Python装饰器的概念、功能及相关使用技巧,需要的朋友可以参考下
本文实例讲述了 Python 装饰器(decorator)定义与用法。分享给大家供大家参考,具体如下:
什么是装饰器(decorator)
简单来说,可以把装饰器理解为一个包装函数的函数,它一般将传入的函数或者是类做一定的处理,返回修改之后的对象.所以,我们能够在不修改原函数的基础上,在执行原函数前后执行别的代码.比较常用的场景有日志插入,事务处理等.
装饰器
最简单的函数,返回两个数的和
def calc_add(a, b): return a + b calc_add(1, 2)
但是现在又有新的需求,计算求和操作耗时,很简单,求和前获取一下时间,求和后再获取一次,求差即可
import datetime def calc_add(a, b): start_time = datetime.datetime.now() result = a + b end_tiem = datetime.datetime.now() print "result:", result, "used:", (end_tiem - start_time).microseconds, "μs" return result calc_add(1, 2)
现在呢,函数calc_diff(a, b)
,计算a-b,也想计算减法操作的时间差,很好办,把那段代码复制过去.但是假如我们现在想编的是一个数学函数库,各种函数都想计算其执行耗时,总不能一个一个复制代码,想个更好的办法.
我们知道,在Python中函数也是被视为对象的,可以作为参数传递,那么假如把计算耗时的独立为一个单独的函数calc_spend_time()
,然后把需要计算耗时的函数例如calc_add的引用传递给它,在calc_spend_time中调用calc_add,这样所有的需要计算耗时的函数都不用修改自己的代码了.
def calc_spend_time(func, *args, **kargs): start_time = datetime.datetime.now() result = func(*args, **kargs) end_tiem = datetime.datetime.now() print "result:", result, "used:", (end_tiem - start_time).microseconds, "μs" def calc_add(a, b): return a + b calc_spend_time(calc_add, 1, 1) # calc_spend_time(calc_add, a=1, b=2)
看起来也不错,负责计算的函数不用更改,只需调用的时候作为参数传给计算时间差的函数.但就是这,调用的时候形式变了,不再是clac(1, 2),而是calc_spend_time(clac_add, 1, 2),万一calc_add大规模被调用,那么还得一处一处找,然后修改过来,还是很麻烦.如果想不修改代码,就得使clac()
和calc_spend_time(clac)
效果一样,那么可以在calc_spend_time()
里把传入的clac包装一下,然后返回包装后的新的函数,再把返回的包装好的函数赋给clac,那么calc()的效果就和上例calc_spend_time(calc())
效果一样.
import datetime def calc_spend_time(func): def new_func(a, b): start_time = datetime.datetime.now() result = func(a, b) end_tiem = datetime.datetime.now() print "result:", result, "used:", (end_tiem - start_time).microseconds, "μs" return new_func def calc_add(a, b): return a + b calc_add = calc_spend_time(calc_add) calc_add(1, 2)
语法糖
上面的例子就是装饰器的概念,包装函数的函数.事实上上面的例子还可以更精简
import datetime def calc_spend_time(func): def new_func(a, b): start_time = datetime.datetime.now() result = func(a, b) end_tiem = datetime.datetime.now() print "result:", result, "used:", (end_tiem - start_time).microseconds, "μs" return new_func @calc_spend_time def calc_add(a, b): return a + b calc_add(1, 2)
@calc_spend_time
就是语法糖,它的本质就是:calc_add = calc_spend_time(calc_add)
无参数的函数装饰器
import datetime def calc_spend_time(func): def new_func(*args, **kargs): start_time = datetime.datetime.now() result = func(*args, **kargs) end_tiem = datetime.datetime.now() print "result:", result, "used:", (end_tiem - start_time).microseconds, "μs" return new_func @calc_spend_time def calc_add(a, b): return a + b @calc_spend_time def calc_diff(a, b): return a - b calc_add(a=1, b=2) calc_diff(1, 2)
注:
*args:把所有的参数按出现顺序打包成list
**kargs:把所有的key=value形式的参数打包成一个dict
带参数的函数装饰器
假如我们需要知道函数的一些额外信息,例如函数作者,可以通过给装饰器函数增加参数来实现.
import datetime def calc_spend_time(author): def first_deco(func): def new_func(*args, **kargs): start_time = datetime.datetime.now() result = func(*args, **kargs) end_tiem = datetime.datetime.now() print author, "result:", result, "used:", (end_tiem - start_time).microseconds, "μs" return new_func return first_deco @calc_spend_time('author_1') def calc_add(a, b): return a + b @calc_spend_time('author_2') def calc_diff(a, b): return a - b calc_add(a=1, b=2) calc_diff(1, 2)
Python内置装饰器
Python内置的装饰器有三个:staticmethod,classmethod和property.
staticmethod:把类中的方法定义为静态方法,使用staticmethod装饰的方法可以使用类或者类的实例对象来调用,不需要传入self
class Human(object): """docstring for Human""" def __init__(self): super(Human, self).__init__() @staticmethod def say(message): if not message: message = 'hello' print 'I say %s' % message def speak(self, message): self.say(message) Human.say(None) human = Human() human.speak('hi')
输出:
I say hello I say hi
classmethod:把类中的方法定义为类方法,使用classmethod装饰的方法可以使用类或者类的实例对象来调用,并将该class对象隐式的作为第一个参数传入
class Human(object): """docstring for Human""" def __init__(self): super(Human, self).__init__() self.message = '111' def say(message): if not message: message = 'hello' print 'I say %s' % message @classmethod def speak(cls, message): if not message: message = 'hello' cls.say(message) human = Human() human.speak('hi')
输出同上例
property:把方法变成属性
class Human(object): """docstring for Human""" def __init__(self, value): super(Human, self).__init__() self._age = value @property def age(self): return self._age human = Human(20) print human.age
更多关于Python相关内容可查看本站专题:《Python数据结构与算法教程》、《Python Socket编程技巧总结》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》及《Python入门与进阶经典教程》
希望本文所述对大家Python程序设计有所帮助。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- SQLAlchemy框架用法详解
- Elasticsearch SQL 用法详解
- SQL中Merge用法详解
- Linux sort命令用法详解
- golang包time用法详解
- Python中with用法详解
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Python核心编程(第3版)
[美] Wesley Chun / 孙波翔、李斌、李晗 / 人民邮电出版社 / 2016-5 / CNY 99.00
《Python核心编程(第3版)》是经典畅销图书《Python核心编程(第二版)》的全新升级版本,总共分为3部分。第1部分为讲解了Python的一些通用应用,包括正则表达式、网络编程、Internet客户端编程、多线程编程、GUI编程、数据库编程、Microsoft Office编程、扩展Python等内容。第2部分讲解了与Web开发相关的主题,包括Web客户端和服务器、CGI和WSGI相关的We......一起来看看 《Python核心编程(第3版)》 这本书的介绍吧!
HTML 压缩/解压工具
在线压缩/解压 HTML 代码
HSV CMYK 转换工具
HSV CMYK互换工具