【Python基础】Python 装饰器(优雅的代码增强工具)

news2024/9/20 12:23:17

本文收录于 《Python编程入门》专栏,从零基础开始,分享一些Python编程基础知识,欢迎关注,谢谢!

文章目录

    • 一、前言
    • 二、装饰器基础
    • 三、语法糖 @
    • 四、带参数的装饰器
    • 五、多层装饰器
    • 六、总结

一、前言

在Python编程的世界里,装饰器是一种独特且强大的工具,它允许程序员在不修改原函数代码的情况下,为函数添加新的功能或行为。

本文将带您探索装饰器的奥秘,看看它们是如何工作的,以及它们能为我们带来哪些便利。

  • 什么是Python?

    Python是由荷兰人吉多·范罗苏姆于1990年初设计的一门高级编程语言,该语言应用领域非常广泛,尤其在数据科学、人工智能、游戏开发等领域,它已经成为最受欢迎的程序设计语言之一,非常适合新手学习。

    Python语言标准库官方使用手册:https://docs.python.org/zh-cn/3/library/turtle.html#turtle-methods

  • Python语言有哪些特点?

    1.易于学习:Python有相对较少的关键字,结构简单,和一个明确定义的语法,学习起来更加简单。

    2.易于阅读:Python代码定义的更清晰。

    3.易于维护:Python的成功在于它的源代码是相当容易维护的。

    4.丰富的库:Python的最大的优势之一具有丰富的标准库,并且跨平台的,在UNIX,Windows和Mac兼容很好。

    5.面向对象:Python支持面向对象编程,在“面向对象”的语言中,程序是由数据和功能组合而成的对象构建起来的。

    6.可移植:基于其开放源代码的特性,Python已经被移植(也就是使其工作)到许多平台。

    7.可扩展:如果你需要一段运行很快的关键代码,或者是想要编写一些不愿开放的算法,你可以使用C或C++完成那部分程序,然后从你的Python程序中调用。

    8.可嵌入: 你可以将Python嵌入到C/C++程序,让你的程序的用户获得"脚本化"的能力。

    在这里插入图片描述

二、装饰器基础

装饰器本质上是一个函数,它接受另一个函数作为参数,并返回一个新的函数。这个新的函数通常在原函数的基础上增加了一些额外的行为。

例如,我们有一个简单的函数 foo():

def foo():
    print('hello foo')

如果我们希望在调用 foo() 时记录函数的执行时间,可以使用装饰器,如下:

import time

# 定义一个装饰器函数,记录执行时间
def show_time(func):
    def wrapper():
        start_time = time.time()
        func()
        end_time = time.time()
        duration = end_time - start_time
        print(f"函数 {func.__name__} 执行时间为:{duration:.3f} 秒")
    return wrapper

# 调用装饰器函数,记录执行时间
@show_time
def foo():
    print('hello foo')
    time.sleep(3)

foo()

"""
输出:
hello foo
函数 foo 执行时间为:3.002 秒
"""

在上述例子中,show_time 是一个装饰器,它接受函数 foo 作为参数,并返回一个新的函数 wrapper。wrapper 函数在调用 func() 前后记录时间,从而实现了在不修改 foo 函数代码的情况下,增加了时间记录的功能。

三、语法糖 @

Python 提供了 @ 语法糖来简化装饰器的使用。在定义 foo 函数时使用 @show_time,避免了显式地将 foo 函数传递给 show_time 并赋值的步骤,如下:

# 使用@ 语法糖方式,调用装饰器函数,记录执行时间
@show_time
def foo():
    print('hello foo')
    time.sleep(3)

四、带参数的装饰器

有时我们希望装饰器能够接收参数,以便根据不同的需求进行定制。

例如,我们希望根据标志决定是否将执行时间记录到日志中。

import time

# 定义一个装饰器函数,记录执行时间
def time_logger(flag):
    def show_time(func):
        def wrapper():
            start_time = time.time()
            func()
            end_time = time.time()
            duration = end_time - start_time
            print(f"函数 {func.__name__} 执行时间为:{duration:.3f} 秒")
            if flag:
                print('将这个操作的时间记录到日志中')
        return wrapper
    return show_time

# 调用装饰器函数,记录执行时间
@time_logger(flag=True)
def foo():
    print('hello foo')
    time.sleep(3)

foo()

"""
输出
hello foo
函数 foo 执行时间为:3.013 秒
将这个操作的时间记录到日志中

"""

在这个例子中,time_logger 是一个带有参数的装饰器,它返回一个内部装饰器 show_time。通过 @time_logger(flag=True),我们可以在不修改 bar 函数代码的前提下,根据 flag 的值来决定是否记录日志。

五、多层装饰器

多层装饰器允许我们在函数上应用多个装饰器,从而实现更复杂的功能。装饰器的执行顺序是从最外层向内层执行,而调用顺序则相反,从内层向外层执行。

例如:

# 定义装饰器make_bold
def make_bold(func):
    def wrapper():
        return "<b>" + func() + "</b>"
    return wrapper

# 定义装饰器make_italic
def make_italic(func):
    def wrapper():
        return "<i>" + func() + "</i>"
    return wrapper

# 使用装饰器make_bold和装饰器make_italic
@make_bold
@make_italic
def hello():
    return "hello alvin"

print(hello())  # 输出:<b><i>hello alvin</i></b>

在上述例子中,hello 函数先被 make_italic 装饰,再被 make_bold 装饰。因此,hello() 的返回值首先被 make_italic 包裹,再被 make_bold 包裹。

六、总结

Python 装饰器是一种优雅的代码增强工具,它允许我们在不修改原函数代码的情况下,为函数添加额外的功能。装饰器广泛应用于日志记录、性能测试、事务处理、缓存和权限校验等场景。掌握装饰器的使用,可以显著提高代码的复用性和可读性,使程序设计更加灵活和模块化。

如果您对文章中内容有疑问,欢迎在评论区进行留言,我会尽量抽时间给您回复。如果文章对您有帮助,欢迎点赞、收藏。您的点赞,是对我最大的支持和鼓励,谢谢 :-)

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

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

相关文章

【手撕】快排-分治

1. 颜色分类 . - 力扣&#xff08;LeetCode&#xff09;. - 备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/sort-colors/description/ 代码 class Solution {public…

Neo4j入门案例:三星堆

创建一个关于三星堆的知识图谱可以是一个非常有趣的项目&#xff0c;它可以帮助理解如何使用Neo4j来存储和查询复杂的关系数据。三星堆文化以其独特的青铜器、金器和其他文物而闻名&#xff0c;这为我们提供了一个丰富的历史背景来构建知识图谱。 数据模型定义 实体类型&#…

数据安全查询-—SAAS本地化及未来之窗行业应用跨平台架构

一、数据库安全查询 默认数据库查询是不区分大小写的&#xff0c;这样无法区分Mm&#xff0c;Admin&#xff0c;admin 二、thinkphp 区分大小写 $condition "binary appdhj_sn {$应用sn}"; 三、原始mysql select * from TableA where binary columnA aaa; 四、…

mtk7628 网口灯问题

板子上电插入网线到网口&#xff0c;只有wan口灯会亮&#xff0c;插入lan口灯不会亮。对比了ok的代码&#xff0c;先对比设备树&#xff0c;未看到网口相关的GPIO。 mt7628an_WMD-7688A-12816.dts mt7628an_hilink_hlk-7628n.dts 继续查看网口相关代码&#xff0c;加打印&…

Android应用程序启动源码分析

文章目录 Android应用程序启动源码分析一、启动流程二、Launcher通知AndroidOS(用户点击图标)2.1 Activity.java2.2 Instrumentation.java2.3 ActivityTaskManagerService.java2.4 ActivityStarter.java2.5 RootWindowContainer.java2.5.1 Task.java2.5.2 TaskFragment.java 2.…

基于python+django+vue的个性化餐饮管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于pythondjangovueMySQL的视…

勇于尝试,永远行动 - 《洛克菲勒写给儿子的38封信》读书笔记

两倍速听过好几遍的书&#xff0c;洛克菲勒的思想和志向&#xff0c;配得上他的成就。 “在尝试中寻找突破&#xff0c;在行动中成就自我。”这是洛克菲勒写给儿子的箴言&#xff0c;也是他一生的真实写照。在这38封信中&#xff0c;他不仅分享了自己的工作心得&#xff0c;更…

Docker安装mysql安装nginx安装Redis

Docker安装mysql 下载镜像 docker pull mysql:8.0注意,使用此方法安装镜像需要提前配置镜像源,详情看之前的文章 安装 docker run -d -p 3306:3306 \ --name mysql \ --restartalways \ --privilegedtrue \ -e TZAsia/Shanghai \ -e MYSQL_ROOT_PASSWORDroot \ mysql:8.0进…

【重学 MySQL】二十九、函数的理解

【重学 MySQL】二十九、函数的理解 什么是函数不同 DBMS 函数的差异函数名称和参数功能实现数据类型支持性能和优化兼容性和可移植性 MySQL 的内置函数及分类单行函数多行函数&#xff08;聚合函数&#xff09;使用注意事项 什么是函数 函数&#xff08;Function&#xff09;在…

【PHP代码审计】 PHP环境搭建

&#x1f31d;博客主页&#xff1a;泥菩萨 &#x1f496;专栏&#xff1a;Linux探索之旅 | 网络安全的神秘世界 | 专接本 | 每天学会一个渗透测试工具 安装phpstudy 泥菩萨-CSDN博客 安装vscode 直接去官网下载安装包&#xff0c;然后双击安装即可。官网地址&#xff1a;htt…

24/9/15 kaggle数字识别器

这次做的是数字识别器&#xff0c;借鉴了大佬的文章Kaggle竞赛实战系列&#xff08;一&#xff09;&#xff1a;手写数字识别器&#xff08;Digit Recognizer&#xff09;得分99.53&#xff05;、99.91%和100%_手写数字识别实现 digist-CSDN博客 加入了自己对大佬里面步骤的解…

多模态大语言模型综述(中)-算法实用指南

本文是Multimodal Large Language Models: A Survey的译文之算法实用指南部分。 上&#xff1a;摘要、概念与技术要点实用指南中&#xff1a;算法实用指南(本文)下: 任务的实用指南(应用)、挑战等 原始信息 标题: Multimodal Large Language Models: A Survey译文: 多模态大…

Conda和pip 清空缓存

conda clean --all然后选y&#xff0c;如下图&#xff1a; pip cache purge # 清除所有缓存

视频工具EasyDarwin将本地视频生成RTSP给WVP拉流列表

效果 ffmpeg生成rtsp流 EasyDarwin的rtsp端口默认的是10054, 使用ffmpeg将本地视频转到EasyDarwin的rtsp。 F:\rtsp\ffmpeg-7.0.2-essentials_build\bin>ffmpeg -re -i F:\rtsp\123.mp4 -rtsp_transport tcp -vcodec h264 -f rtsp rtsp://127.0.0.1:10054/video11 它的直播…

【C#】vs2022 .net8

Visual Studio 2022 IDE - 适用于软件开发人员的编程工具 (microsoft.com) 更新就会出现

2024年【浙江省安全员-C证】考试试卷及浙江省安全员-C证模拟考试题库

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 浙江省安全员-C证考试试卷是安全生产模拟考试一点通总题库中生成的一套浙江省安全员-C证模拟考试题库&#xff0c;安全生产模拟考试一点通上浙江省安全员-C证作业手机同步练习。2024年【浙江省安全员-C证】考试试卷及…

【裸机装机系列】6.kali(ubuntu)-图形界面优化-让linux更适合你的使用习惯

接下来就是图形化界面操作的部分了。会用少量截图来说明&#xff0c;图太多会影响阅读体验&#xff0c;直接文字来描述过程吧。 1> 入口 任务栏左上角——> 开始菜单——> settings——> settings manager 大部分配置都会在这里面设置。 2> 设置里面分的4大…

移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——13.mapset

1. 关联式容器 在初阶阶段&#xff0c;我们已经接触过STL中的部分容器&#xff0c;比如&#xff1a;vector、list、deque、 forward_list(C11)等&#xff0c;这些容器统称为序列式容器&#xff0c;因为其底层为线性序列的数据结构&#xff0c;里面 存储的是元素本身。那什么是关…

HCIA--实验十五:ACL通信实验(1)

1.基本ACL配置 一、实验内容 1.需求/要求&#xff1a; 使用一台交换机&#xff0c;两台PC&#xff0c;通过在交换机上配置基本ACL&#xff0c;实现拒绝PC1到PC2的访问。 二、实验过程 1.拓扑图 2.步骤 1.给PC1和PC2配置ip地址&#xff1a; 2.在交换机SW1上做ACL的配置 […

QT模型视图结构1

文章目录 Qt 模型视图结构概述(一)1、模型/视图结构基本原理2、模型3、视图4、代理5、简单实例 Qt 模型视图结构概述(一) ​ 模型/视图结构是一种将数据存储和界面展示分离的编程方法。模型存储数据&#xff0c;视图组件显示模型中的数据&#xff0c;在视图组件里修改的数据会…