内容简介:这篇文章主要介绍了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用法详解
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
500 Lines or Less
Amy Brown、Michael DiBernardo / 2016-6-28 / USD 35.00
This book provides you with the chance to study how 26 experienced programmers think when they are building something new. The programs you will read about in this book were all written from scratch t......一起来看看 《500 Lines or Less》 这本书的介绍吧!