欢迎大家来到IT世界,在知识的湖畔探索吧!
欢迎大家来到IT世界,在知识的湖畔探索吧!
装饰器是 Python 中一个强大的特性,可以帮助简化代码并提高可维护性。在本文中,我们将探讨如何使用装饰器来避免重复代码,并使修改多个函数的功能变得更加容易。
常见编码问题:重复代码
日常编码原则:Dont Reat Yourself
让我们考虑一个例子,我们有两个函数 add 和 multiply,它们执行一些计算并记录执行时间。
import time def add(num1: int, num2: int): """计算两个数字之和,统计耗时""" start = time.time() print(f"Add {num1} and {num2}") res = num1 + num2 end = time.time() print(f'Elapsed time: {(end - start) * 1000:.3f}ms') return res def multiply(num1: int, num2: int): """计算两数相乘并统计耗时""" start = time.time() print(f"Multiply {num1} and {num2}") res = num1 * num2 end = time.time() print(f'Elapsed time: {(end - start) * 1000:.3f}ms') return res add(1, 2) multiply(1, 2)
欢迎大家来到IT世界,在知识的湖畔探索吧!
输出:
欢迎大家来到IT世界,在知识的湖畔探索吧!Add 1 and 2 Elapsed time: 0.142ms Multiply 1 and 2 Elapsed time: 0.006ms 2
正如我们所见,计时逻辑在两个函数中都重复了。如果我们需要修改计时逻辑,我们不得不在两个地方都进行更新,这既耗时又容易出错。
pythonic的解决方案:装饰器
装饰器可以帮助我们避免重复代码,并使修改多个函数的功能变得更加容易。
让我们定义一个装饰器 time_func,它可以用来跟踪任何函数的执行时间。
import time def time_func(func): def wrapper(*args, kwargs): start = time.time() res = func(*args, kwargs) end = time.time() print(f'Elapsed time: {(end - start) * 1000:.3f}ms') return res return wrapper
这里是装饰器的逐步解释:
- time_func 接受一个函数 func 作为参数。
- 内部的 wrapper 函数处理任意数量的位置参数和关键字参数。
- 它记录开始时间,调用原始函数并传递原始参数,然后记录结束时间。
- 计算并打印经过的时间。
- 返回原始函数的结果。
现在我们可以将 time_func 装饰器应用到我们的 add 和 multiply 函数上。
欢迎大家来到IT世界,在知识的湖畔探索吧!@time_func def add(num1: int, num2: int): """计算两个数字之和,统计耗时""" print(f"Add {num1} and {num2}") return num1 + num2 @time_func def multiply(num1: int, num2: int): """计算两数相乘并统计耗时""" print(f"Multiply {num1} and {num2}") return num1 * num2 add(1, 2) multiply(1, 2)
输出:
Add 1 and 2 Elapsed time: 0.453ms Multiply 1 and 2 Elapsed time: 0.007ms 2
正如我们所见,计时逻辑现在定义在一个地方,如果需要修改,我们可以轻松地进行调整。
保留函数元数据
当我们使用 time_func 装饰器时,它会改变函数的名称和文档字符串。为了保留原始函数的元数据,我们推荐使用 functools 模块中的 wraps 装饰器。
欢迎大家来到IT世界,在知识的湖畔探索吧!import time from functools import wraps def time_func_with_wraps(func): @wraps(func) def wrapper(*args, kwargs): start = time.time() res = func(*args, kwargs) end = time.time() print(f'Elapsed time: {(end - start) * 1000:.3f}ms') return res return wrapper
现在我们可以将 time_func_with_wraps 装饰器应用到我们的 add 和 multiply 函数上。
@time_func_with_wraps def add(num1: int, num2: int): """计算两个数字之和,统计耗时""" print(f"Add {num1} and {num2}") return num1 + num2 @time_func_with_wraps def multiply(num1: int, num2: int): """计算两数相乘并统计耗时""" print(f"Multiply {num1} and {num2}") return num1 * num2 add(1, 2) multiply(1, 2)
输出:
欢迎大家来到IT世界,在知识的湖畔探索吧!Add 1 and 2 Elapsed time: 0.332ms Multiply 1 and 2 Elapsed time: 0.008ms 2
正如我们所见,函数的名称和文档字符串现在被保留了。
print(f"Function name: {add.__name__}") print(f"Docstring: {add.__doc__}")
输出:
欢迎大家来到IT世界,在知识的湖畔探索吧!Function name: add Docstring: 计算两个数字之和,统计耗时
了解更多Pythonic最佳实践
Python是一个非常优雅的语言,前提是你要了解最pythonic的用法,《改善python代码质量的实用技巧》专栏专门整理了各种pythonic的方式来编写最适合python语言的方式来写符合对应口味和风格的代码,感兴趣的同学可以异步专栏了解更多。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/116677.html