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")这样的语法,我们可以为不同的函数指定不同的日志级别进行装饰。

相关文章

干货 | 一文讲清楚Python之装饰器

概念介绍装饰器(decorator),又称“装饰函数”,即一种返回值也是函数的函数,可以称之为“函数的函数”。其目的是在不对现有函数进行修改的情况下,实现额外的功能。最基本的理念来自于一种被称为“装饰...

Python修饰器,终极解释来了!

修饰器在本质上就是一个函数,可接收其他函数作为参数。接下来,让我们看看如何自定义一个修饰器#这个修饰器可在被修饰函数之前被执行 def xiushi1(func): print("定义...

Python 装饰器:如何改进代码的功能和可读性

什么是装饰器?用装饰器来扩展另一个函数的功能。通过使用装饰器,可以添加其他功能。为了定义装饰器,需要定义一个函数,该函数具有一个调用 wrapper 的函数和一个调用 func, 的参数,该参数是我们...

Python的装饰器还是不会?来看看这篇文章(建议收藏)

点赞、收藏、加关注,下次找我不迷路哈喽,各位 Python 爱好者们!今天咱们要一起来攻克 Python 里一个超实用却又让不少新手犯迷糊的知识点 —— 装饰器。别担心,全程用大白话,搭配例子,还有...

python装饰器详解

装饰器储备知识1:*args和**kwargs储备知识2:名称空间与作用域储备知识3:函数对象储备知识4:函数的嵌套定义储备知识 5:闭包函数喜欢编程的小伙伴可以加小编的Q群1026782549,进群...

Python中自带的三个装饰器

说到装饰器,就不得不说python自带的三个装饰器:1、@property 将某函数,做为属性使用@property 修饰,就是将方法,变成一个属性来使用。2、@classmethod 修饰类的方式带...