资讯专栏INFORMATION COLUMN

Python装饰器都有什么用呢

89542767 / 374人阅读

  小编写这篇文章的主要目的,就是给大家介绍关于python装饰器的用途方面的知识,这样对我们以后的工作也是有一定的帮助,具体用途是什么呢?下面就给各位读者详细的解答下。


  装饰器自身的价值显而易见,可以加强函数值基本功能、简单化编码、降低代码冗余。


  它的使用场景同样很多,比较简单的场景包含打印日志、统计运行时间,这类例子和用法网上已经很多了:


  def time_dec(func):
  def wrapper(*arg):
  t=time.clock()
  res=func(*arg)
  print func.func_name,time.clock()-t
  return res
  return wrapper
  time_dec
  def myFunction(n):
  ...


  再进阶一些的,可以用来校验函数传入参数类型、线程同步、单元测试等:


  parameters(
  (2,4,6),
  (5,6,11),
  )
  def test_add(a,b,expected):
  assert a+b==expected


  目前可以用的装饰器可以分为如下几类:


  自定义


  第三方工具包


  内置


  下面就分别来介绍一下。


  自定义


  关于自定义的装饰器在前面已经提到了,我在开发过程中经常用到的就是日志打印、计时、数据校验等场景,通过装饰器可以提高代码的简洁性,避免重复造轮子。


  除了这些基本的,也有一些比较实用的地方。


  作为开发同学,肯定会遇到不同的运行环境:


  开发环境


  测试环境


  生产环境


  有时候,我们期望一个函数在不同环境下执行不同的过程,产出不同的结果,做一些环境的隔离和差异化处理。


  通过装饰器就可以很好的解决:


  production_servers=[...]
  def production(func:Callable):
  def inner(*args,**kwargs):
  if gethostname()in production_servers:
  return func(*args,**kwargs)
  else:
  print('This host is not a production server,skipping function decorated with production...')
  return inner
  
  def development(func:Callable):
  def inner(*args,**kwargs):
  if gethostname()not in production_servers:
  return func(*args,**kwargs)
  else:
  print('This host is a production server,skipping function decorated with development...')
  return inner
  
  def sit(func:Callable):
  def inner(*args,**kwargs):
  print('Skipping function decorated with sit...')
  return inner
  
  production
  def foo():
  print('Running in production,touching databases!')
  
  foo()
  
  development
  def foo()
   print('Running in production,touching databases!')
  foo()
  inactive
  def foo():
  print('Running in production,touching databases!')
  foo()


  简单介绍一下一下子这一段源代码。


  在这儿,一开始列举了环境个性化服务榜单,随后各自界定了制造、研发、测试流程的装饰器,并给同名的的变量就能够加上对应装饰器。


  在执行代码的过程中,这一段源代码会首先获取hostname,自动判断所在环境,随后执行对应变量。


  第三方工具包


  上面是根据我们在开发过程中遇到的个性化场景进行来自界定一个装饰器。


  作为一款以工具包著称的编程语言,Python中也有很多工具包提供了一些实用的装饰器。


  以日志为例,这是每个程序员都无法绕开的。


  调试程序对于大多数开发者来说是一项必不可少的工作,当我们想要知道源代码是否按照预期的效果在执行时,我们会想到去输出一下子局部变量与预期的进行比对。目前大多数采用的方法主要有以下几种:


  Print函数


  Log日志


  IDE调试器


  但是这些方法有着无法忽视的弱点:


  繁琐


  过度依赖工具


  其中有一款不错的开源工具PySnooper就通过装饰器把这个问题巧妙的解决了。


  PySnooper的调用方式就是通过pysnooper.snoop的方式进行使用,该装饰器可以传入一些参数来实现一些目的,具体如下:


  参数描述:


  None输出日志到控制台


  filePath输出到日志文件,例如'log/file.log'


  prefix给调试的行加前缀,便于识别


  watch查看一些非局部变量表达式的值


  watch_explode展开值用以查看列表/字典的所有属性或项


  depth显示函数调用的函数的snoop行


  举个例子:


  import numpy as np
  import pysnooper
  pysnooper.snoop()
  def one(number):
  mat=[]
  while number:
  mat.append(np.random.normal(0,1))
  number-=1
  return mat
  one(3)


  然后,就会给出如下输出:


  Starting var:..number=3


  22:17:10.634566 call 6 def one(number):


  22:17:10.634566 line 7 mat=[]


  New var:.......mat=[]


  22:17:10.634566 line 8 while number:


  22:17:10.634566 line 9 mat.append(np.random.normal(0,1))


  Modified var:..mat=[-0.4142847169210746]


  22:17:10.634566 line 10 number-=1


  Modified var:..number=2


  22:17:10.634566 line 8 while number:


  22:17:10.634566 line 9 mat.append(np.random.normal(0,1))


  Modified var:..mat=[-0.4142847169210746,-0.479901983375219]


  22:17:10.634566 line 10 number-=1


  Modified var:..number=1


  22:17:10.634566 line 8 while number:


  22:17:10.634566 line 9 mat.append(np.random.normal(0,1))


  Modified var:..mat=[-0.4142847169210746,-0.479901983375219,1.0491540468063252]


  22:17:10.634566 line 10 number-=1


  Modified var:..number=0


  22:17:10.634566 line 8 while number:


  22:17:10.634566 line 11 return mat


  22:17:10.634566 return 11 return mat


  Return value:..[-0.4142847169210746,-0.479901983375219,1.0491540468063252]


  局部变量值、代码片段、局部变量所在行号、返回结果等,这些关键信息都输出了,既方便,又清晰。


  内置


  除了自定义和第三方工具包之外,Python还内置了很多不错的装饰器,例如abc.abstractmethod、asyncio.coroutine、classmethod等等。


  这里着重提一个非常强大的装饰器,能够极大的提升Python的运行速度和效率,通过一个装饰器能够将Python代码的执行速度提升上万倍,这个装饰器就是functools.lru_cache。


  以比较知名的斐波那契数列的例子来演示一下。


  由于它递归计算的过程中,还会用到之前计算的结果,因此会涉及较多的重复计算,下面先看一下正常计算的耗时情况。


  import time as tt
  def fib(n):
  if n<=1:
  return n
  return fib(n-1)+fib(n-2)
  t1=tt.time()
  fib(30)
  print("Time taken:{}".format(tt.time()-t1))
  #0.2073


  n等于30时,耗时0.2073。


  加上functools.lru_cache装饰器再看一下:


  import time as tt
  import functools
  functools.lru_cache(maxsize=5)
  def fib(n):
  if n<=1:
  return n
  return fib(n-1)+fib(n-2)
  t1=tt.time()
  fib(30)
  print("Time taken:{}".format(tt.time()-t1))
  #1.811981e-05


  耗时为1.811981e-05,足足差了4个量级,快了10000+倍!


  到此为止,关于Python装饰器作用相关知识就为大家介绍到这里了,希望可以为各位读者带来帮助


文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/127784.html

相关文章

  • Python装饰器高级用法

    摘要:在中,装饰器一般用来修饰函数,实现公共功能,达到代码复用的目的。智能装饰器上节介绍的写法,嵌套层次较多,如果每个类似的装饰器都用这种方法实现,还是比较费劲的脑子不够用,也比较容易出错。假设有一个智能装饰器,修饰装饰器,便可获得同样的能力。 在Python中,装饰器一般用来修饰函数,实现公共功能,达到代码复用的目的。在函数定义前加上@xxxx,然后函数就注入了某些行为,很神奇!然而,这只...

    AlphaWallet 评论0 收藏0
  • 利用世界杯,读懂 Python 装饰

    摘要:今天就结合最近的世界杯带大家理解下装饰器。而德国是上届的冠军,又是这届夺冠热门。装饰器的存在是为了适用两个场景,一个是增强被装饰函数的行为,另一个是代码重用。在利用语法糖,简化赋值操作。行为良好的装饰器可以重用,以减少代码量。 Python 装饰器是在面试过程高频被问到的问题,装饰器也是一个非常好用的特性,熟练掌握装饰器会让你的编程思路更加宽广,程序也更加 pythonic。 show...

    xiguadada 评论0 收藏0
  • Python的@装饰器是干什么用的?

    摘要:那么,这个装饰器要怎么定义呢我们来看一下。当然了,如果大家在网络上搜索,关于如何定义装饰器,看到的是一个更加规范的版本。在当中,调用原函数时又,即把输入的元祖解包再传入。 ...

    NusterCache 评论0 收藏0
  • Python: 会打扮的装饰

    摘要:一般情况下,我们使用装饰器提供的语法糖,来简化上面的写法像上面的情况,可以动态修改函数或类功能的函数就是装饰器。本文标题为会打扮的装饰器本文链接为参考资料修饰器的函数式编程中的装饰器介绍思诚之道装饰器入门与提高赖明星 装饰器 我们知道,在 Python 中,我们可以像使用变量一样使用函数: 函数可以被赋值给其他变量 函数可以被删除 可以在函数里面再定义函数 函数可以作为参数传递给另外...

    blastz 评论0 收藏0
  • python3常用3种装饰器词法归纳

      此篇文章主要是详细介绍了python3常用3种装饰器语法总结,文中根据实例编码为大家介绍得非常详尽,对大家学习培训和工作具有很强的参照参考意义,需用的小伙伴可以借鉴一下  python3常用3种装饰器语法总结  1.概述词法  装饰器又称函数公式装饰器,主要是的作用是在没有改动原先函数的编码前提下(函数公式自身不被改动,实现方式都不转变),提升的另一个"装饰设计"函数公式,...

    89542767 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<