python装饰器的作用和功能,python装饰器--原来如此简单
本文主要介绍Python decorator的妙用,通过示例代码非常详细的介绍,对大家的学习或工作有一定的参考价值。有需要的朋友就跟着下面的边肖学习吧。
00-1010自定义第三方工具包内置装饰器的价值不言而喻,可以用来增强功能,简化代码,减少代码冗余。
它还有很多使用场景。简单的场景包括打印日志和计算运行时间。网上有很多这样的例子和用法:
def time_dec(函数):
def包装(*arg):
t=time.clock()
res=func(*arg)
print func.func_name,time.clock()-t
返回资源
返回包装
@time_dec
定义我的功能(n):
.
更高级的是,它可以用来检查传入函数的参数类型、线程同步、单元测试等。
@参数(
(2, 4, 6),
(5, 6, 11),
)
def test_add(a,b,预期):
断言a b==预期
目前可以使用的装修工可以分为以下几类:
定制的第三方工具包是内置的。下面分别介绍一下。
目录
自定义装饰器之前已经提到过。我经常使用日志打印、计时、数据验证等场景。在开发过程中。通过装饰器,我们可以提高代码的简单性,避免重复制作轮子。
除了这些基础,还有一些实用的地方。
作为开发同学,你肯定会遇到不同的运行环境:
开发环境测试环境生产环境有时候,我们期望一个功能在不同的环境下执行不同的流程,产生不同的结果,做一些环境隔离和区分。
装修工可以很好的解决:
生产服务器=[.]
定义生产(func:可调用):
def inner(*args,**kwargs):
如果生产服务器:中的gethostname()
return func(*args,**kwargs)
else:
print(此主机不是生产服务器,跳过用@production .修饰的函数。)
返回内部
定义开发(func:可调用):
def inner(*args,**kwargs):
如果gethostname()不在生产服务器:中
return func(*args,**kwargs)
else:
print(该主机是生产服务器,跳过用@development修饰的函数.)
返回内部
def sit(func:可调用):
def inner(*args,**kwargs):
print(跳过用@sit .修饰的函数)
返回内部
@生产
def foo():
打印(“在生产中运行,接触数据库!”)
foo()
@发展
def foo():
打印(“在生产中运行,接触数据库!”)
foo()
@不活跃
def foo():
打印(“在生产中运行,接触数据库!”)
foo()
简单介绍一下这段代码。
这里先列出生产环境的服务列表,然后再单独定义。
了生产、开发、测试环境的装饰器,然后给同名的函数就可以配上对应的装饰器。
在执行代码的过程中,这段代码会首先获取hostname,自动判断所在环境,然后执行对应函数。
第三方工具包
上面是根据我们在开发过程中遇到的个性化场景进行来自定义一个装饰器。
作为一款以工具包著称的编程语言,Python中也有很多工具包提供了一些实用的装饰器。
以日志为例,这是每个程序员都无法绕开的。
调试程序对于大多数开发者来说是一项必不可少的工作,当我们想要知道代码是否按照预期的效果在执行时,我们会想到去输出一下局部变量与预期的进行比对。目前大多数采用的方法主要有以下几种:
- Print函数
- Log日志
- IDE调试器
但是这些方法有着无法忽视的弱点:
- 繁琐
- 过度依赖工具
其中有一款不错的开源工具PySnooper就通过装饰器把这个问题巧妙的解决了。
PySnooper的调用方式就是通过@pysnooper.snoop的方式进行使用,该装饰器可以传入一些参数来实现一些目的,具体如下:
参数描述:
- None输出日志到控制台
- filePath输出到日志文件,例如'log/file.log'
- prefix给调试的行加前缀,便于识别
- watch查看一些非局部变量表达式的值
- watch_explode展开值用以查看列表/字典的所有属性或项
- depth显示函数调用的函数的snoop行
举个例子:
import numpy as npimport 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 ttdef 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 ttimport 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装饰器有哪些绝妙的用法的文章就介绍到这了,更多相关Python装饰器内容请搜索盛行IT软件开发工作室以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT软件开发工作室!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。