温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Python装饰器decorator怎么用

发布时间:2021-08-03 12:33:23 来源:亿速云 阅读:151 作者:小新 栏目:开发技术

这篇文章主要介绍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内置的装饰器有三个:staticmethodclassmethodproperty

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装饰器decorator怎么用”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注亿速云行业资讯频道!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI