当前位置:首页 > 技术分析 > 正文内容

Python的装饰器

一、装饰器的基本概念

  1. 定义

在 Python 中,装饰器(Decorator)是一种特殊的函数,它可以用于修改其他函数的功能。装饰器本质上是一个返回函数的高阶函数,它接受一个函数作为参数,并返回一个新的函数,这个新函数通常会在原函数的基础上添加一些额外的功能,如日志记录、性能测试、权限验证等。

  1. 示例

假设我们有一个简单的函数func,我们想要在调用这个函数时记录一些信息,比如函数被调用的时间。我们可以定义一个装饰器来实现这个功能。

import time
def log_time(func):
    def wrapper():
        start_time = time.time()
        func()
        end_time = time.time()
        print(f"函数 {func.__name__} 执行时间为: {end_time - start_time}秒")
    return wrapper
def func():
    print("这是原函数")
    time.sleep(2)
func = log_time(func)
func()

在这个例子中,log_time就是一个装饰器函数。它接受一个函数func作为参数,然后在内部定义了一个新的函数wrapper。这个wrapper函数会在调用原函数func之前记录开始时间,调用func之后记录结束时间,然后计算并打印出函数的执行时间。最后,装饰器函数返回wrapper函数。通过func = log_time(func)这一行,我们将原函数func替换为了经过装饰器修饰后的函数。当我们最后调用func()时,实际上调用的是wrapper()函数,从而实现了在原函数基础上添加记录执行时间的功能。

二、装饰器的语法糖

  1. 语法糖介绍

使用@符号是 Python 提供的装饰器语法糖,可以让装饰器的使用更加简洁。上面的例子可以改写为:

import time
def log_time(func):
    def wrapper():
        start_time = time.time()
        func()
        end_time = time.time()
        print(f"函数 {func.__name__} 执行时间为: {end_time - start_time}秒")
    return wrapper
@log_time
def func():
    print("这是原函数")
    time.sleep(2)
func()

当在函数定义前加上@log_time时,就相当于执行了func = log_time(func)这一步骤,使得代码更加简洁易读。

三、装饰器的参数传递

  1. 带有参数的函数的装饰

如果被装饰的函数带有参数,那么装饰器内部的wrapper函数也需要接收这些参数。例如,我们有一个函数add_numbers,它接受两个参数并返回它们的和。

def log_time(func):
    def wrapper(x, y):
        start_time = time.time()
        result = func(x, y)
        end_time = time.time()
        print(f"函数 {func.__name__} 执行时间为: {end_time - start_time}秒")
        return result
    return wrapper
@log_time
def add_numbers(x, y):
    return x + y
print(add_numbers(3, 5))

在这个例子中,wrapper函数接收了x和y两个参数,然后将它们传递给原函数func,并获取返回结果。最后,wrapper函数返回这个结果,并且在计算执行时间后打印出来。

  1. 装饰器本身带参数的情况

有时候,我们可能希望装饰器本身也可以接收参数,来实现更加灵活的功能。例如,我们想要一个可以根据不同的日志级别来记录日志的装饰器。

import logging
def log_with_level(level):
    def decorator(func):
        def wrapper(*args, **kwargs):
            if level == "DEBUG":
                logging.basicConfig(level = logging.DEBUG)
            elif level == "INFO":
                logging.basicConfig(level = logging.INFO)
            # 其他级别设置
            result = func(*args, **kwargs)
            logging.log(getattr(logging, level), f"函数 {func.__name__} 被调用")
            return result
        return wrapper
    return decorator
@log_with_level("INFO")
def another_function():
    print("这是另一个函数")
another_function()

在这个例子中,log_with_level是一个外层函数,它接收一个日志级别参数level。它返回一个装饰器函数decorator,这个装饰器函数接受一个函数func作为参数,并返回wrapper函数。wrapper函数根据传入的日志级别进行日志配置,调用原函数func,记录日志,然后返回结果。通过@log_with_level("INFO")这样的语法,我们可以为不同的函数指定不同的日志级别进行装饰。

扫描二维码推送至手机访问。

版权声明:本文由ruisui88发布,如需转载请注明出处。

本文链接:http://www.ruisui88.com/post/4707.html

标签: kwargs.get
分享给朋友:

“Python的装饰器” 的相关文章

美国民众负债累累 但今年假期消费者支出仍将创下新高

智通财经APP获悉,在迎接假期之际,许多美国人已经背负了创纪录的信用卡债务。然而,今年假期消费者支出仍将创下新高。根据美国零售联合会(NRF)上周发布的报告,预计今年11月1日至12月31日期间的消费总额将达到创纪录的9795亿至9890亿美元之间。NRF首席经济学家Jack Kleinhenz表示...

前端路由简介以及vue-router实现原理

作者:muwoo 来源:https://zhuanlan.zhihu.com/p/37730038后端路由简介路由这个概念最先是后端出现的。在以前用模板引擎开发页面时,经常会看到这样http://www.xxx.com/login 大致流程可以看成这样:浏览器发出请求服务器监听到80 端口(或443...

慕课 SpringBoot2.X+Vue+UniAPP,全栈开发医疗小程序

本课程以业务驱动技术栈,打造业务相对完整的掌上医疗小程序,解决大家没有好的毕设项目或者求职项目的困境。本课程案例采用前后端分离架构,业务功能完善(既有WEB管理端,也有移动用户端),界面美观,无需艰涩的技术也能做出亮眼的作品。SpringBoot2.X+Vue+UniAPP,全栈开发医疗小程序 |...

推荐一个Java微服务商业级Sass开源电商小程序(开源,企业级项目)

使用Java微服务开发,SpringBoot2框架、MyBatis-plus持久层框架、Redis作为缓存、MySql8作为数据库。 前端vuejs作为开发语言,使用uniapp编码,同时支持微信小程序、安卓App、苹果App。 支持集群部署,单机部署。 unimall 针对中小商户、企业和个人消...

企业微信自建应用和消息发送配置对接系统指南

本文介绍企业微信应用创建、消息提醒、自动回复、自定义菜单和服务端接口对接过程。企业微信登录:https://work.weixin.qq.com/企业微信接口对接,应用授权和发送消息代码:https://www.easywechat.com/docs/5.x/wework/oauth一、创建自建应用...

什么是同步通信?什么是异步通信?它们有什么区别?

串行通信一般又分为同步和异步通信,同步通信需要同步时钟信号,而异步通信则不需要同步时钟信号。同步通信:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式。异步通信:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。同步通信与异步通信有什么区别呢?1、同步通信要求接收端...