优化重复冗余代码的pythonic的方式

B站影视 2025-01-13 05:03 3

摘要:装饰器是 Python 中一个强大的特性,可以帮助简化代码并提高可维护性。在本文中,我们将探讨如何使用装饰器来避免重复代码,并使修改多个函数的功能变得更加容易。

装饰器是 Python 中一个强大的特性,可以帮助简化代码并提高可维护性。在本文中,我们将探讨如何使用装饰器来避免重复代码,并使修改多个函数的功能变得更加容易。

日常编码原则:Dont Reat Yourself

让我们考虑一个例子,我们有两个函数 add 和 multiply,它们执行一些计算并记录执行时间。

import timedef add(num1: int, num2: int):"""计算两个数字之和,统计耗时"""start = time.timeprint(f"Add {num1} and {num2}")res = num1 + num2end = time.timeprint(f'Elapsed time: {(end - start) * 1000:.3f}ms')return resdef multiply(num1: int, num2: int):"""计算两数相乘并统计耗时"""start = time.timeprint(f"Multiply {num1} and {num2}")res = num1 * num2end = time.timeprint(f'Elapsed time: {(end - start) * 1000:.3f}ms')return resadd(1, 2)multiply(1, 2)

输出:

Add 1 and 2Elapsed time: 0.142msMultiply 1 and 2Elapsed time: 0.006ms2

正如我们所见,计时逻辑在两个函数中都重复了。如果我们需要修改计时逻辑,我们不得不在两个地方都进行更新,这既耗时又容易出错。

装饰器可以帮助我们避免重复代码,并使修改多个函数的功能变得更加容易。

让我们定义一个装饰器 time_func,它可以用来跟踪任何函数的执行时间。

import timedef time_func(func):def wrapper(*args, **kwargs):start = time.timeres = func(*args, **kwargs)end = time.timeprint(f'Elapsed time: {(end - start) * 1000:.3f}ms')return resreturn wrapper

这里是装饰器的逐步解释:

time_func 接受一个函数 func 作为参数。内部的 wrapper 函数处理任意数量的位置参数和关键字参数。它记录开始时间,调用原始函数并传递原始参数,然后记录结束时间。计算并打印经过的时间。返回原始函数的结果。

现在我们可以将 time_func 装饰器应用到我们的 add 和 multiply 函数上。

@time_funcdef add(num1: int, num2: int):"""计算两个数字之和,统计耗时"""print(f"Add {num1} and {num2}")return num1 + num2@time_funcdef multiply(num1: int, num2: int):"""计算两数相乘并统计耗时"""print(f"Multiply {num1} and {num2}")return num1 * num2add(1, 2)multiply(1, 2)

输出:

Add 1 and 2Elapsed time: 0.453msMultiply 1 and 2Elapsed time: 0.007ms2

正如我们所见,计时逻辑现在定义在一个地方,如果需要修改,我们可以轻松地进行调整。

当我们使用 time_func 装饰器时,它会改变函数的名称和文档字符串。为了保留原始函数的元数据,我们推荐使用 functools 模块中的 wraps 装饰器

import timefrom functools import wrapsdef time_func_with_wraps(func):@wraps(func)def wrapper(*args, **kwargs):start = time.timeres = func(*args, **kwargs)end = time.timeprint(f'Elapsed time: {(end - start) * 1000:.3f}ms')return resreturn wrapper

现在我们可以将 time_func_with_wraps 装饰器应用到我们的 add 和 multiply 函数上。

@time_func_with_wrapsdef add(num1: int, num2: int):"""计算两个数字之和,统计耗时"""print(f"Add {num1} and {num2}")return num1 + num2@time_func_with_wrapsdef multiply(num1: int, num2: int):"""计算两数相乘并统计耗时"""print(f"Multiply {num1} and {num2}")return num1 * num2add(1, 2)multiply(1, 2)

输出:

Add 1 and 2Elapsed time: 0.332msMultiply 1 and 2Elapsed time: 0.008ms2

正如我们所见,函数的名称和文档字符串现在被保留了。

print(f"Function name: {add.__name__}")print(f"Docstring: {add.__doc__}")Function name: addDocstring: 计算两个数字之和,统计耗时

python是一个非常优雅的语言,前提是你要了解最pythonic的用法,《改善python代码质量的实用技巧》专栏专门整理了各种pythonic的方式来编写最适合python语言的方式来写符合对应口味和风格的代码,感兴趣的同学可以异步专栏了解更多。

来源:SuperOps

相关推荐