使用Python怎么实现一个函数装饰器

  介绍

这篇文章将为大家详细讲解有关使用Python怎么实现一个函数装饰器,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

Python可以做什么

Python是一种编程语言,内置了许多有效的工具,Python几乎无所不能,该语言通俗易懂,容易入门,功能强大,在许多领域中都有广泛的应用,例如最热门的大数据分析,人工智能,网页开发等。

<强>跟踪调用

如下代码定义并应用一个函数装饰器,来统计对装饰的函数的调用次数,并且针对每一次调用打印跟踪信息。

class 示踪剂:   def 才能__init__(自我,函数):   ,,,self.calls =0   ,,,self.func =函数   def 才能__call__(自我,* args):   ,,,self.calls  +=1   ,,,print (& # 39; call  % s 用% & # 39;,% (self.calls, self.func.__name__))   ,,,self.func (* args)   @tracer   def 垃圾邮件(a, b, c):   打印才能(a  +, b  +, c)

这是一个通过类装饰的语法写成的装饰器、测试如下:

在祝辞祝辞,垃圾邮件(1、2、3)   call  1,用垃圾邮件   6   祝辞祝辞祝辞,垃圾邮件(& # 39;一个# 39;& # 39;b # 39;, & # 39; c # 39;)   call  2,用垃圾邮件   美国广播公司   在祝辞祝辞spam.calls   2   在祝辞祝辞,垃圾邮件   & lt; __main__.tracer  object  at  0 x03098410>

运行的时候,示踪剂类和装饰的函数分开保存,并且拦截对装饰的函数的随后的调用,以便添加一个逻辑层来统计和打印每次调用。

装饰之后,垃圾邮件实际上是示踪剂类的一个实例。

@装饰器语法避免了直接地意外调用最初的函数。考虑如下所示的非装饰器的对等代码:

calls =0   * args def 示踪(函数):   global 才能调用   calls 才能+=1   打印才能(& # 39;call  % s 用% & # 39;%(电话,func.__name__))   ,,func (* args)   def 垃圾邮件(a, b, c):   打印才能(a + b + c)

测试如下:

在祝辞祝辞,垃圾邮件(1、2、3)   6   在祝辞祝辞,示踪剂(垃圾邮件,1、2、3)   call  1,用垃圾邮件   6

这一替代方法可以用在任何函数上,且不需要特殊的@语法,但是和装饰器版本不同,它在代码中调用函数的每个地方都需要额外的语法。尽管装饰器不是必需的,但是它们通常是最为方便的。

<强>扩展——支持关键字参数

下述代码时前面例子的扩展版本,添加了对关键字参数的支持:

class 示踪剂:   def 才能__init__(自我,函数):   ,,,self.calls =0   ,,,self.func =函数   def 才能__call__(自我,* args, * * kargs):   ,,,self.calls  +=1   ,,,print (& # 39; call  % s 用% & # 39;,% (self.calls, self.func.__name__))   ,,,self.func (* args, * * kargs)   @tracer   def 垃圾邮件(a, b, c):   打印才能(a  +, b  +, c)   @tracer   def 蛋(x, y):   打印才能(x * * y)

测试如下:

在祝辞祝辞,垃圾邮件(1、2、3)   call  1,用垃圾邮件   6   在祝辞祝辞,垃圾邮件(=4,b=5, c=6)   call  2,用垃圾邮件   15   在祝辞祝辞,蛋(2,16)   call  1,用鸡蛋   65536   在祝辞祝辞,鸡蛋(4,y=4)   call  2,用鸡蛋   256年

也可以看的到,这里的代码同样使用【类实例属性】来保存状态,即调用的次数<代码>自我。电话>

<强>使用def函数语法写装饰器

使用def定义装饰器函数也可以实现相同的效果。但是有一个问题,我们也需要封闭作用域中的一个计数器,它随着每次调用而更改。我们可以很自然地想到全局变量,如下:

calls =0   def 示踪(函数):   def 才能包装器(* args, * * kargs):   ,,,global 调用   ,,,calls  +=1   ,,,print (& # 39; call  % s 用% & # 39;%(电话,func.__name__))   ,,,return  func (* args, * * kargs)   return 才能包装   @tracer   def 垃圾邮件(a, b, c):   打印才能(a + b + c)   @tracer   def 蛋(x, y):   打印才能(x * * y)

这电话里定义为全局变量,它是跨程序的,是属于整个模块的,而不是针对每个函数的,这样的话,对于任何跟踪的函数调用,计数器都会递增,如下测试:

使用Python怎么实现一个函数装饰器