python decorator wrapper_python3进阶系列05:补充下装饰器decorator用法

我们之前在入门总结的时候,写了一个模拟停车场收费的程序,主要逻辑就是利用车辆入场时间和出场时间间隔来计费。如果现在我们想要计算一个函数的执行时间,也可以这样计算时间间隔。

from datetime import datetime

import time

def fib2(n):

start = datetime.now()

a,b = 0,1

result = []

while n>1:

result.append(b)

a,b = b,a+b

n -= 1

print(result)

time.sleep(2)

end = datetime.now()

print('函数:{},时间:{}'.format(fib2.__name__,(end-start).seconds))

return result

我们以之前的求斐波那契数列为例,在函数的开始和结束时加入时间记录,最后输出函数名称__name__(python函数内置属性)和执行时间。显然这样统计时间会侵入到函数中,而且这种可以公用的东西最好单独定义一个函数。

这种情况下,我们可以使用装饰器(decorator),在调用函数的时候动态增强代码功能,简单来说就是一个包装函数,由包装函数触发目标函数。下面我们看一下这个包装函数。

def timeelaps(func):

def wrapper(*tuple_args,**dict_args):

start = datetime.now()

result = func(*tuple_args,**dict_args)

end = datetime.now()

print((end-start).seconds)

return result

return wrapper

@timeelaps

def hello():

print('hello','小麦’)

如上,我们使用一个可以传入目标函数的函数,然后在该函数中执行需要增强的代码,然后再调用目标函数,然后我们使用@函数名注解到目标函数上。

此时执行hello()实际是执行hello=timeelpas(hello),此时的hello已经指向了包装函数timeelpas,返回的是wrapper函数,在wrapper中又调用了目标函数。唯一美中不足的就是此时hello的函数名称变成了wrapper,破坏了对象的完整性。我们可以使用@functools.wraps(func)来保持原有对象信息。只需加在wrapper函数上。下面我们看一下包装函数也需要参数的情况。

import functools

def timeelaps1(title):

def decorator(func):

@functools.wraps(func)

def wrapper(*tuple_args,**dict_args):

print(title)

return func(*tuple_args,**dict_args)

return wrapper

return decorator

@timeelaps1('小麦')

def hello():

print('hello','小麦')

同理这里的hello实际等价于hello=timeelaps1('小麦')(hello),返回一个decorator函数,然后传入hello函数在wrapper中执行,简单理解就是把上面的包装函数又包装了一层。

装饰器的思想就就是装饰模式,在不改变原代码的情况下,通过继承组合动态扩展对象的功能,也就是通过装饰来包装真实对象,今天我们就补充到这里。下一节我们继续讲文件IO。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值