def time_it(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(func.__name__ + "took " + str((end - start)*1000) + "mil sec")
return result
return wrapper
@time_it
def calc_square(nums):
result = []
for num in nums:
result.append(num*num)
return result
array = range(1, 100000)
out_square = calc_square(array)
这段代码实现了一个装饰器time_it,它是一个非常实用的Python功能,用于修改或增强已有函数或方法的行为,而不需要改变原来函数的代码。下面我会逐步解释这段代码是如何构建的,以及它的工作原理:
步骤 1: 理解装饰器的基本概念
装饰器本质上是一个函数,它接受一个函数作为参数,并返回一个新的函数。装饰器的目的是在不修改原函数代码的情况下,给函数添加新的功能。
步骤 2: 定义装饰器
在这个例子中,time_it就是一个装饰器。它的目标是测量任何函数执行时间的功能。
def time_it(func):
def wrapper(*args, **kwargs):
...
return wrapper
这里,time_it接受一个函数func作为参数。然后,它定义了一个内部函数wrapper,这个内部函数将被返回,并替换掉原来的func。wrapper可以接受任意数量的位置参数和关键字参数,这样无论func需要哪些参数,wrapper都能正确地传递。
步骤 3: 添加功能
在wrapper函数内部,我们添加了测量时间的功能。
start = time.time() # 记录开始时间
result = func(*args, **kwargs) # 调用原始函数,并传递任何参数
end = time.time() # 记录结束时间
print("calc_square took " + str((end - start)*1000) + "mil sec")
# 打印执行时间
首先,记录下函数开始执行的时间。然后,通过func(*args, **kwargs)调用原始函数(即装饰器外部的函数),并将所有接收到的参数传递给它。执行完毕后,记录下结束时间。计算这两个时间点之间的差,转换为毫秒,并打印出来。
步骤 4: 返回新函数
最后,time_it装饰器返回wrapper函数。这个返回的函数将替换掉原来用@time_it装饰的函数。
如何使用这个装饰器
假设你有一个函数calc_square,你想测量它的执行时间,你可以这样做:
@time_it
def calc_square(nums):
...
在calc_square函数定义之前加上@time_it,就等于是告诉Python:“请用time_it装饰器来装饰这个函数”。这样每次调用calc_square时,实际上是调用了time_it返回的wrapper函数,wrapper函数会先执行计时逻辑,然后调用原始的calc_square函数。
总的来说,这个装饰器是一个非常实用的工具,可以用来给函数添加各种各样的“前置”或“后置”操作,比如计时、日志记录、参数校验等,而不需要改变原有函数的代码。