2022年 11月 5日

python学习笔记–运行时间装饰器cal_time自定义

在学习的时候发现直接调用装饰器可以很方便接入查询时间的函数

  1. from cal_time import *
  2. @cal_time
  3. def quick_sort(li):
  4. """
  5. data
  6. """
  7. quick_sort(li)
  8. # 这样就很方便

所以怎么才能使用装饰器呢

1.首先装饰器可以调用time函数,然后直接在方法上面加入@就行

  1. import time
  2. def show_time(func):
  3. def wrapper():
  4. star = time.process_time()
  5. func()
  6. end= time.process_time()
  7. print('spend_time:',end-star)
  8. return wrapper
  9. @show_time
  10. def func():
  11. print('test')
  12. func()

这是一种方法调用可以使用show_time的装饰器进行修饰

2.其外还可以传入参数。直接传入wrapper当中。

  1. import time
  2. def show_time(func):
  3. def wrapper(a,b):
  4. star = time.process_time()
  5. func(a,b)
  6. end= time.process_time()
  7. print('spend_time:',end-star)
  8. return wrapper
  9. @show_time
  10. def add(a, b):
  11. print(a + b)
  12. add(3,5)

这里可以想到,要是实际情况需要传入很多个参数,我手不得写麻,而且后期还不好维护,所以可以用python带的参数args,kwargs

  1. import time
  2. def show_time(func):
  3. def wrapper(*args, **kwargs):
  4. star = time.process_time()
  5. func(*args,**kwargs)
  6. end= time.process_time()
  7. print('spend_time:',end-star)
  8. return wrapper
  9. @show_time
  10. def add(*args, **kwargs):
  11. sum = 0
  12. for i in args:
  13. sum += i
  14. print(sum)
  15. add(22,13,44,5,6,3,62)

其实就是把传入的参数改成args和kwargs两个可变参数。

这里有一个问题,当加入装饰器之后,函数的name,doc元信息都是消失啦,写的时候就会改变。

如上:

  1. @show_time
  2. def test():
  3. print("cake")
  4. print(test.__name__) # wrapper
  5. def test2():
  6. print('cake2')
  7. print(test2.__nmae__) # test2

所以,python有一个方法functools的wraps,在方法上面加入@wraps(func) ,就可以复用当前的元信息

  1. from functools import wraps
  2. def show_time(func):
  3. @wraps(func)
  4. def wrapper():
  5. func()
  6. return wrapper
  7. @show_time
  8. def test():
  9. print('test_demo')
  10. print(test.__name__)
  11. def test1():
  12. print('test1_demo')
  13. print(test1.__name__)

其中还可以在装饰器中传入参数,flag是True

  1. import time
  2. def cal_time(flag):
  3. def show_time(func):
  4. def wrapper(*args, **kwargs):
  5. star = time.process_time()
  6. func(*args, **kwargs)
  7. end = time.process_time()
  8. if flag == 'True':
  9. print('spend_time:',end-star)
  10. return wrapper
  11. return show_time
  12. @cal_time("True")
  13. def add(*args, **kwargs):
  14. sum = 0
  15. for i in args:
  16. sum += 1
  17. print(sum)
  18. add(1,45,3,2,14)

甚至还有类装饰器,具有高灵活性、高内聚、封装性的特点。

  1. import time
  2. class Foo(object):
  3. def __init__(self, func):
  4. self.func = func
  5. def __call__(self):
  6. star = time.process_time()
  7. self.func()
  8. end = time.process_time()
  9. print('spend_time:', end-star)
  10. @Foo
  11. def bar():
  12. print('test')
  13. bar()

类名Foo可以直接作为装饰器,用call调用。

当然还有内置的装饰器,晚点学习

  1. @a
  2. @b
  3. @c
  4. def f():
  5. 相当于 f = a(b(c(f)))