decorator
装饰器 可以给函数动态加上功能,对于类的方法,装饰器一样起作用。
既要保护类的封装特性,又要让开发者可以使用“对象.属性”的方式操作操作类属性,除了使用 property() 函数,Python 还提供了 @property 装饰器。通过 @property 装饰器,可以直接通过方法名来访问方法,不需要在方法名后添加一对“()”小括号。
@property 的语法格式如下:
@property def 方法名(self) 代码块
对实例属性操作的时候,该属性是不直接暴露的,而是通过getter和setter方法来实现的。还可以定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性:
class Rect: def __init__(self,area): self.__area = area @property def area(self): return self.__area @area.setter def area(self, value): self.__area = value @area.deleter def area(self): self.__area = 0 rect = Rect(30) #直接通过方法名来访问 area 方法 print("矩形的面积是:",rect.area) # 为 Rect 类中的 area 方法添加 setter 方法 后 rect.area = 90 print("修改后的面积:",rect.area) del rect.area print("删除后的area值为:",rect.area)
自定义装饰器
参考文章:https://zhuanlan.zhihu.com/p/85917478
def wrapper(func): def inner(*args,**kwargs): '''被装饰函数之前''' ret = func(*args,**kwargs) '''被装饰函数之后''' return ret return inner
编写一个装饰器函数`log_time`,被装饰的函数执行时打印出【函数名】与【执行时间】(时间单位为秒,只需保留小数点后一位,见测试示例)。
注:装饰器函数要具备通用性,即被装饰函数允许传入位置参数与关键字参数。
import time import functools def log_time(func): @functools.wraps(func) def inner(*args, **kwargs):
'''执行前相关操作''' t_begin = time.time() ret = func(*args, **kwargs)
'''执行后相关操作''' print('%s: Function [saySomething] took %0.1f seconds to execute' % (func.__name__, time.time()-t_begin)) return ret return inner # 这里是测试代码 @log_time def salute(word): time.sleep(2) print(word) salute('hello') # 'hello Function [saySomething] took 2.0 seconds to execute'
函数装饰之后,相当于执行了inner函数,所以输出inner,wraps将 被修饰的函数(wrapped) 的一些属性值赋值给修饰器函数(wrapper) ,最终让属性的显示更符合我们的直觉
装饰器传参
import time def timmer(f): def inner(a,b): start_time = time.time() f(a,b) end_time = time.time() print('此函数的执行时间为{}'.format(end_time - start_time)) return inner
@timmer def func1(a,b): print('in func1 {}{}'.format(a,b)) time.sleep(1) # 模拟程序逻辑 func1(1,2) 执行输出: in func1 12 此函数的执行时间为1.0006024837493896
如果有多个参数呢?改成动态参数
import time def timmer(f): def inner(*args,**kwargs): start_time = time.time() f(*args,**kwargs) end_time = time.time() print('此函数的执行时间为{}'.format(end_time - start_time)) return inner @timmer def func1(*args,**kwargs): print('in func1 {}{}'.format(args,kwargs)) time.sleep(1) # 模拟程序逻辑 func1(1,2,a='3',b=4) 执行输出: in func1 (1, 2){'b': 4, 'a': '3'} 此函数的执行时间为1.000101089477539
函数的执行时,*打散 ; 函数的定义时,*聚合。
import time #1.加载模块 def timmer(*args,**kwargs): #2.加载变量 5.接收参数True,2,3 def wrapper(f): #6.加载变量 8.f = func1 print(args, kwargs) #9.接收timmer函数的值True,2,3 def inner(*args,**kwargs): #10.加载变量. 13.执行函数inner if flag: #14 flag = True start_time = time.time() #15 获取当前时间 ret = f(*args,**kwargs) #16 执行func1 time.sleep(0.3) #19 等待0.3秒 end_time = time.time() #20 获取当前时间 print('此函数的执行效率%f' % (end_time-start_time)) #21 打印差值 else: ret = f(*args, **kwargs) return ret #22 返回给函数调用者func1() return inner #11 返回给函数调用者wrapper return wrapper #7.返回给函数调用timmer(flag,2,3) flag = True #3 加载变量 @timmer(flag,2,3) # 4.执行函数timmer(flag,2,3) 17.执行函数func1 两步:1,timmer(flag,2,3) 相当于执行wrapper 2.@wrapper 装饰器 func1 = wrapper(func1) def func1(*args,**kwargs): return 666 #18 返回给函数调用者f(*args,**kwargs) print(func1()) #12 执行函数
装饰器的 __name__ 和 __doc___
__name__:函数名
__doc___:函数的解释