Python 装饰器可以将代码减少一半

一、说明

        这里,我将与您分享一些令人惊叹的 Python 装饰器,它们可以将您的代码减少一半。听起来好得令人难以置信,对吧?好吧,让我向您展示它们是如何工作的以及为什么应该在项目中使用它们。

二、什么是 Python 装饰器?

        Python 装饰器是一个强大的功能,允许您修改函数或类的行为而不更改其源代码。它们本质上是接受另一个函数作为参数并返回一个包装原始函数的新函数的函数。这样,您可以在不修改原始函数的情况下添加一些额外的功能或逻辑。

        例如,假设您有一个将消息打印到控制台的函数:

def hello():print("Hello, world!")

        现在,假设您想要测量执行此函数需要多长时间。您可以编写另一个函数,使用该time模块计算执行时间,然后调用原始函数:

import timedef measure_time(func):def wrapper():start = time.time()func()end = time.time()print(f"Execution time: {end - start} seconds")return wrapper

        请注意,该measure_time函数返回另一个名为 的函数wrapper,它是原始函数的修改版本。该wrapper函数做了两件事:记录执行的开始和结束时间,并调用原始函数。

        现在,要使用此功能,您可以执行以下操作:

hello = measure_time(hello)
hello()

        这会输出类似这样的内容:

<span style="background-color:#f9f9f9"><span style="color:#242424">你好世界!
执行时间:0.000123456789秒</span></span>

        正如您所看到的,我们已经成功地向该hello函数添加了一些额外的功能,而无需更改其代码。然而,有一种更优雅、更简洁的方法可以使用装饰器来完成此操作。装饰器只是语法糖,允许您使用@符号将一个函数应用到另一个函数。例如,我们可以像这样重写之前的代码:

Hello, world!
Execution time: 0.000123456789 seconds

        这将产生与以前相同的输出,但代码要少得多。该@measure_time行相当于说hello = measure_time(hello),但它看起来更干净且更具可读性。

三、为什么使用 Python 装饰器?

        Python 装饰器的用途有很多,例如:

  • 它们允许您重用代码并避免重复。例如,如果您有许多需要测量其执行时间的函数,您可以简单地对所有函数应用相同的装饰器,而不必一遍又一遍地编写相同的代码。
  • 它们允许您分离关注点并遵循单一责任原则。例如,如果您有一个执行某些复杂计算的函数,则可以使用装饰器来处理日志记录、错误处理、缓存或输入和输出的验证,而不会扰乱函数的主要逻辑。
  • 它们允许您扩展现有函数或类的功能,而无需修改其源代码。例如,如果您使用的第三方库提供了一些有用的函数或类,但您想向它们添加一些额外的功能或行为,则可以使用装饰器来包装它们并根据您的需要自定义它们。

四、Python 装饰器的一些示例

        Python 中有很多内置的装饰器,例如@staticmethod@classmethod@property@functools.lru_cache@functools.singledispatch等。您还可以出于各种目的创建自己的自定义装饰器。以下是 Python 装饰器的一些示例,可以将代码减少一半:

1.@timer装饰器

        这个装饰器与我们之前看到的装饰器类似@measure_time,但它可以应用于任何接受任意数量参数并返回任意值的函数。它还使用functools.wraps装饰器来保留原始函数的名称和文档字符串。这是代码:

import time
from functools import wrapsdef timer(func):@wraps(func)def wrapper(*args, **kwargs):start = time.time()result = func(*args, **kwargs)end = time.time()print(f"Execution time of {func.__name__}: {end - start} seconds")return resultreturn wrapper

        现在,您可以使用此装饰器来测量任何函数的执行时间,例如:

@timer
def factorial(n):"""Returns the factorial of n"""if n == 0 or n == 1:return 1else:return n * factorial(n - 1)@timer
def fibonacci(n):"""Returns the nth Fibonacci number"""if n == 0 or n == 1:return nelse:return fibonacci(n - 1) + fibonacci(n - 2)print(factorial(10))
print(fibonacci(10))

        这会输出类似这样的内容:

Execution time of factorial: 1.1920928955078125e-06 seconds
3628800
Execution time of fibonacci: 0.000123456789 seconds
55

2.@debug装饰器

        该装饰器对于调试目的很有用,因为它打印它所包装的函数的名称、参数和返回值。它还使用functools.wraps装饰器来保留原始函数的名称和文档字符串。这是代码:

from functools import wrapsdef debug(func):@wraps(func)def wrapper(*args, **kwargs):print(f"Calling {func.__name__} with args: {args} and kwargs: {kwargs}")result = func(*args, **kwargs)print(f"{func.__name__} returned: {result}")return resultreturn wrapper

现在,您可以使用此装饰器来调试任何函数,例如:

@debug
def add(x, y):"""Returns the sum of x and y"""return x + y@debug
def greet(name, message="Hello"):"""Returns a greeting message with the name"""return f"{message}, {name}!"print(add(2, 3))
print(greet("Alice"))
print(greet("Bob", message="Hi"))

这会输出类似这样的内容:

Calling add with args: (2, 3) and kwargs: {}
add returned: 5
5
Calling greet with args: ('Alice',) and kwargs: {}
greet returned: Hello, Alice!
Hello, Alice!
Calling greet with args: ('Bob',) and kwargs: {'message': 'Hi'}
greet returned: Hi, Bob!
Hi, Bob!

3.@memoize装饰器

        该装饰器对于优化递归或昂贵函数的性能很有用,因为它会缓存先前调用的结果,并在再次传递相同的参数时返回它们。它还使用functools.wraps装饰器来保留原始函数的名称和文档字符串。这是代码:

from functools import wrapsdef memoize(func):cache = {}@wraps(func)def wrapper(*args):if args in cache:return cache[args]else:result = func(*args)cache[args] = resultreturn resultreturn wrapper

        现在,您可以使用此装饰器来记忆任何函数,例如:

@memoize
def factorial(n):"""Returns the factorial of n"""if n == 0 or n == 1:return 1else:return n * factorial(n - 1)
@memoize
def fibonacci(n):"""Returns the nth Fibonacci number"""if n == 0 or n == 1:return nelse:return fibonacci(n - 1) + fibonacci(n - 2)
print(factorial(10))
print(fibonacci(10))

        这将输出与以前相同的结果,但执行时间要快得多,因为结果会被缓存和重用。

五、结论

        Python 装饰器是一种强大而优雅的方法,可以在不更改源代码的情况下修改函数或类的行为。它们可以帮助您将代码减少一半、提高代码可读性、重用代码、分离您的关注点以及扩展现有代码的功能。我希望您喜欢这篇博文并学到一些新东西。如果您有任何问题或意见,请随时在下面留下。不要忘记与可能有兴趣了解有关 Python 装饰器的更多信息的朋友和同事分享这篇文章。谢谢阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/618178.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

都是取所有行的某列数据,这个array[:,2]和array[:,2:3]有什么不同呢

效果图 代码 import numpy as nplist [[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20],[21,22,23,24,25] ] array np.array(list) print(array) 输出&#xff1a; [[ 1 2 3 4 5][ 6 7 8 9 10][11 12 13 14 15][16 17 18 19 20][21 22 23 24 25]]a arr…

想要安利给所有人的开发工具

Visual Studio Code - 一个轻量级且功能丰富的代码编辑器&#xff0c;支持多种编程语言&#xff0c;拥有强大的插件和工具集。 Git - 一个分布式版本控制系统&#xff0c;可以帮助开发团队协作、跟踪代码变更和管理代码库。 Postman - 一个用于API开发和测试的工具&#xff0…

【上分日记】第369场周赛(分类讨论 + 数学 + 前缀和)

文章目录 前言正文1.3000. 对角线最长的矩形的面积2.3001. 捕获黑皇后需要的最少移动次数3.3002. 移除后集合的最多元素数3.3003. 执行操作后的最大分割数量 总结尾序 前言 终于考完试了&#xff0c;考了四天&#xff0c;也耽搁了四天&#xff0c;这就赶紧来补这场周赛的题了&a…

关于文件上传功能的安全方面的考量

文章目录 场景安全实现 场景 最近做了一个文件上传的功能&#xff0c;下面说进行了哪些方面实现 安全实现 验证登录验证登录用户是否有文件上传接口的权限限制文件大小检验文件后缀,文件头文件单独存储&#xff0c;可以考虑使用第三方服务 比如:七牛云设置文件的rwx权限, rw根…

【Linux实用篇】项目部署 基于Shell脚本自动部署

目录 1. 项目部署 1.1 手动部署项目 1.2 基于Shell脚本自动部署 1.2.1 介绍 1.2.2 推送代码到远程 1.2.3 Git操作 1.2.4 Maven安装 1.2.5 Shell脚本准备 1.2.6 Linux权限 1.2.7 授权并执行脚本 1.2.8 设置静态IP 1. 项目部署 之前我们讲解Linux操作系统时&#xff0…

Dcoker构建部署Java项目过程

目录 前言 一、打包 二、Docker File文件编写 一个简单的Docker File文件 三、上传文件 四、构建镜像 五、运行 六、端口开放 前言 使用Dcoker构建部署Java项目&#xff0c;发布到服务器 一、打包 我这里打包的是item-service这个module&#xff0c;clean-cpmpile-pa…

uniapp 查找不到uview-ui文件怎么办?

用官方的方式总是报&#xff1a;文件查找失败&#xff1a;uview-ui at main.js 解决方案&#xff1a; 1.先安装uview-ui npm install uview-ui 下载成功是这样的&#xff1a; 而不是这样的&#xff1a; 这样的原因是你的项目里没有package.json包&#xff0c;先执行 npm …

Ubuntu平台上C语言利用matio库读取mat文件

一、安装matio库 matio库是一个用于读取和写入MAT文件&#xff08;MATLAB数据格式&#xff09;的开源C库。它提供了一组函数和工具&#xff0c;使得在C和C程序中可以方便地读取和写入MAT文件中的数据。MAT文件是MATLAB软件中常用的文件格式&#xff0c;用于存储多维数值数组、…

Qt 调试系统输出报警声以及添加资源

文章目录 前言一、方法1 使用 Qsound1.添加都文件 直接报错2.解决这个错误 添加 QT multimedia3. 加入代码又遇到新的错误小结 二、第二种方法1.引入库2.添加资源2.1依次点击Qt--->Qt Resource File--->Choose2.2给资源文件起个名字&#xff0c;如&#xff1a;res&#…

【每日一题】构造限制重复的字符串

文章目录 Tag题目来源解题思路方法一&#xff1a;贪心空间复杂度&#xff1a; O ( ∑ ) O(\sum) O(∑)。 写在最后 Tag 【贪心】【字符串】【2024-01-13】 题目来源 2182. 构造限制重复的字符串 解题思路 方法一&#xff1a;贪心 思路 解题思想比较简单&#xff0c;利用贪…

【MySQL】:掌握SQL中DDL的数据库定义与操作

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; MySQL从入门到进阶 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1;前言一. SQL的分类二. DDL数据库操作2.1 查询所有数据库2.2 查询当前数据库2.3 创建数…

[足式机器人]Part2 Dr. CAN学习笔记-Advanced控制理论 Ch04-8 状态观测器设计 Linear Observer Design

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN学习笔记-Advanced控制理论 Ch04-8 状态观测器设计 Linear Observer Design

虚幻引擎nDisplay教程:如何同步nDisplay节点与Switchboard + Helix Core

对于使用大型LED屏幕进行拍摄的虚拟制作团队来说&#xff0c;虚幻&#xff08;Unreal&#xff09;的nDisplay是一个重要的工具。但是&#xff0c;在nDisplay中将正确版本的文件发送到每个节点会非常耗时。立即阅读本文&#xff0c;您将了解到如何使用Perforce Helix Core版本控…

Linux 系统之部署 ZFile 在线网盘服务

一、ZFile 介绍 1&#xff09;ZFile 简介 官网&#xff1a;https://www.zfile.vip/ GitHub&#xff1a;https://github.com/zfile-dev/zfile ZFile 是一款基于 Java 的在线网盘程序&#xff0c;支持对接 S3、OneDrive、SharePoint、又拍云、本地存储、FTP 等存储源&#xff0…

【Go】excelize库实现excel导入导出封装(三),基于excel模板导出excel

前言 大家好&#xff0c;这里是符华~ 关于excelize库实现excel导入导出封装&#xff0c;我已经写了两篇了&#xff0c;我想要的功能基本已经实现了&#xff0c;现在还差一个模板导出&#xff0c;这篇文章就来讲讲如何实现用模板导出excel。 前两篇&#xff1a; 【Go】excel…

爬虫-5-数据提取-正则,xpath

#免责声明:本文仅供学习&#xff0c;请遵纪守法。 ԅ(ㅂԅ)

Leetcode 剑指 Offer II 061. 查找和最小的 K 对数字

题目难度: 中等 原题链接 今天继续更新 Leetcode 的剑指 Offer&#xff08;专项突击版&#xff09;系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~ 题目描述 给定两个以升序排列的整数数组 nums1 和 nums2 , 以及一个整数 k…

使用CloudCompare对obj网格模型转换为pcd/ply点云模型

1.打开CloudCompare&#xff0c;点击文件夹图标&#xff0c;首先先把文件类型选择为.obj&#xff0c;然后再去找预处理的obj网格模型&#xff0c;点击打开。 2.测试打开的obj网格模型如下图&#xff1a; 3.选中obj文件&#xff0c;点击网格上样本点的图标&#xff0c;输入预生成…

探索 C# 中的程序运行目录获取方法

探索 C# 中的程序运行目录获取方法 引言 在 C# 开发中&#xff0c;有时需要确定您的应用程序的运行目录。这可能是为了读取配置文件、存储日志&#xff0c;或者访问与应用程序位于同一目录的其他资源。C# 提供了几种方法来获取当前程序的运行目录。本文将探讨这些方法及其使用…

群晖Synology Drive同步文件时过滤指定文件夹“dist“, “node_modules“

群晖Synology Drive同步文件时过滤指定文件夹"dist", “node_modules” mac用户 安装Synology Drive创建同步任务修改Synology Drive配置 打开/Users/[用户名]/Library/Application Support/SynologyDrive/data/session/[同步任务序号&#xff0c;第一个同步任务就…