当前位置: 首页 > news >正文

Python装饰器使用方法详解

文章目录

  • 1 装饰器背景知识
    • 1.1 基本概念
    • 1.2 应用场景
  • 2 简单的装饰器代码
  • 3 使用装饰器记录函数执行次数
  • 4 带参数的装饰器
  • 5 装饰器处理有返回值的函数

1 装饰器背景知识

1.1 基本概念

装饰器(Decorator)是 Python 中一种函数或类,用来修饰其他函数或类。装饰器可以改变被装饰函数的行为,或者在调用被装饰函数之前和之后增加额外的操作。装饰器的语法是使用 @ 语法符,在函数定义之前增加装饰器函数的名称。

@decorator_func
def my_func():
    pass

1.2 应用场景

  1. 代码重用:装饰器可以让我们在不更改原函数代码的情况下,为其添加额外的功能。

  2. 日志记录:装饰器可以记录函数的调用日志,帮助我们追踪程序的运行情况。

  3. 权限控制:装饰器可以用来实现函数级别的权限控制,只允许特定的用户访问特定的函数。

  4. 缓存:装饰器可以用来缓存函数的返回值,避免重复计算。

  5. 类型检查:装饰器可以用来在函数调用前检查参数的类型是否符合要求。

  6. 装饰器可以让你在函数或类的定义中添加额外的逻辑,而不更改它们的实现。

2 简单的装饰器代码

def decorator_func(func):
    def wrapper():
        print("Before calling the function")
        func()
        print("After calling the function")
    return wrapper

@decorator_func
def my_func():
    print("Inside the function")

my_func()
# Output: Before calling the function
#         Inside the function
#         After calling the function

上面展示了最简单的装饰器示例代码。在代码中,我们建立了一个名为decorator_func的装饰器和一个名为my_func函数。

  1. 装饰器外部的return必须为装饰器的内部函数,不含括号。通过代码结构可以看出,装饰器本身也是一个闭包。
  2. 在定义装饰器decorator_func时,括号中的’func’指代被装饰器装饰的函数,在这段代码中指代的就是my_func函数。
  3. 在被装饰器装时候,函数的实际执行执行顺序变成了内部函数wrapper所指定的顺序。即先执行print(“Before calling the function”);再执行func()指代的my_func函数;最后执行print(“After calling the function”)。
  4. 本段代码的最终输出为:Before calling the function;Inside the function;After calling the function

3 使用装饰器记录函数执行次数

def cal_times(func):
    l=[]

    def wrapper(*var):
        l.append('1')
        func(*var)
        print("函数执行了%s次"%(len(l)))

    return wrapper


@cal_times
def my_func(i):
    print('%s的平方是%s'%(i,i**2))


my_func(5)
my_func(6)

my_func(i)函数中,我们增加了形参的输入,因此,在装饰器中,也要为之做出更改。此处装饰器中的wrapper函数我们使用*var传参,这种设计方式的优点是可以让这个装饰器适用于任何函数。
再加入了cal_times装饰器后,函数每运行一次,都会使列表l添加一个1,这样可以计算函数的运行次数。这段代码的运行结果如下:
在这里插入图片描述

4 带参数的装饰器

装饰器与函数一样,也可以带入参数,我们在第二节的基础上,对代码做出如下修改:

def decorator_func(param1, param2):
    def decorator(func):
        def wrapper():
            print("Before calling the function with params:", param1,param2)
            func()
            print("After calling the function")
        return wrapper
    return decorator

@decorator_func("hello", "world")
def my_func():
    print("Inside the function")

my_func()

这段代码使用了装饰器来在my_func函数调用前后打印额外的信息,并且装饰器函数decorator_func接受两个参数,在调用wrapper函数时使用这两个参数。
最终,代码将输出:Before calling the function with params: hello world; Inside the function;After calling the function。
如果同时还有字典类型的参数传入,可以使用(*var,**_var)进行解决

5 装饰器处理有返回值的函数

前面我们定义的函数都是执行某种功能,不涉及到return的相关操作。当涉及到处理有返回值的函数时,对于内部函数我们应该使用一个变量将函数的运行结果保存起来,并放在内层函数的return中。为了实现这一功能,我们将第三部分的代码做出如下修改:

def cal_times(func):
    l=[]

    def wrapper(*var):
        l.append('1')
        result = func(*var)
        print("函数执行了%s次"%(len(l)))
        return result

    return wrapper


@cal_times
def my_func(i):
    print('%s的平方是%s'%(i,i**2))
    return i**2


a = my_func(5)
b = my_func(6)

print(a,b)

对于这个装饰器,我们在内部函数wrapper使用result保存运行结果,并将result return,这样a与b就可以被正常的赋值,运行结果如下图。
在这里插入图片描述
而如果不执行保存result并return,a和b将不会得到任何值:
在这里插入图片描述

相关文章:

  • 「python|语言特性」为什么f-string是python中最舒适的字符串格式化方式
  • 8. 好客租房-WebSocket与即时通讯系统[项目必需]
  • 机器学习04 决策树
  • java基础学习 day37 (集合)
  • Python闭包与闭包陷阱
  • 测试篇(三):测试用例的万能公式、对水杯和登录页面设计测试用例、测试用例的设计方法
  • 第十三届蓝桥杯省赛 Java A 组 I 题、Python A 组 I 题、Python B 组 J 题——最优清零方案(AC)
  • 阿里“云开发“小程序(uniCould)
  • 提权漏洞和域渗透历史漏洞整理
  • 传参的理解
  • 基于蜣螂算法的极限学习机(ELM)分类算法-附代码
  • 主流的操作系统(带你快速了解)
  • 六、numpy拷贝
  • STM32+python产生三角波
  • 【计算机网络(考研版)】第一站:计算机网络概述(一)
  • 【附node操作实例】redis简明入门系列—字符串类型
  • 230. Kth Smallest Element in a BST
  • android 一些 utils
  • CSS3 变换
  • SpringCloud集成分布式事务LCN (一)
  • webpack项目中使用grunt监听文件变动自动打包编译
  • 机器学习中为什么要做归一化normalization
  • 浅谈Golang中select的用法
  • 入口文件开始,分析Vue源码实现
  • 携程小程序初体验
  • 400多位云计算专家和开发者,加入了同一个组织 ...
  • Python 之网络式编程
  • (12)目标检测_SSD基于pytorch搭建代码
  • (C语言)逆序输出字符串
  • (JS基础)String 类型
  • (vue)页面文件上传获取:action地址
  • (安全基本功)磁盘MBR,分区表,活动分区,引导扇区。。。详解与区别
  • (编译到47%失败)to be deleted
  • (二)学习JVM —— 垃圾回收机制
  • (附源码)小程序 交通违法举报系统 毕业设计 242045
  • (剑指Offer)面试题41:和为s的连续正数序列
  • (续)使用Django搭建一个完整的项目(Centos7+Nginx)
  • (一)appium-desktop定位元素原理
  • ./include/caffe/util/cudnn.hpp: In function ‘const char* cudnnGetErrorString(cudnnStatus_t)’: ./incl
  • .Net6 Api Swagger配置
  • @property @synthesize @dynamic 及相关属性作用探究
  • [.NET]桃源网络硬盘 v7.4
  • [2016.7.test1] T2 偷天换日 [codevs 1163 访问艺术馆(类似)]
  • [20170713] 无法访问SQL Server
  • [ActionScript][AS3]小小笔记
  • [AIGC] SQL中的数据添加和操作:数据类型介绍
  • [Android Pro] listView和GridView的item设置的高度和宽度不起作用
  • [C++数据结构](22)哈希表与unordered_set,unordered_map实现
  • [C++提高编程](三):STL初识
  • [CISCN2019 华东南赛区]Web4
  • [Deep Learning] 神经网络基础
  • [EMWIN]FRAMEWIN 与 WINDOW 的使用注意
  • [ERROR] 不再支持目标选项 5。请使用 7 或更高版本
  • [Excel] vlookup函数
  • [GXYCTF2019]BabyUpload1 -- 题目分析与详解