欢迎访问宙启技术站
智能推送

Python中的装饰器函数详解

发布时间:2023-12-03 14:39:17

装饰器是Python中一个非常有用的概念,可以用于给函数或类添加额外的功能。实际上,装饰器本身也是一个函数,它接受一个函数作为参数,并返回一个新的函数。这个新的函数通常会在原有函数的基础上添加一些额外的功能,如打印日志、计时、权限验证等。

装饰器的语法比较简单,就是在要装饰的函数的定义之前加上一个@符号,后面紧跟着装饰器函数的名称。例如:

@decorator

def func():

    pass

下面我们来详细了解一下装饰器的使用。

装饰器函数的定义方式如下:

def decorator(func):

    def wrapper(*args, **kwargs):

        # 添加额外的功能

        return func(*args, **kwargs)

    return wrapper

装饰器函数接受一个函数作为参数,并返回一个新的函数。新的函数通常会在原有函数的基础上添加一些额外的功能,这些功能写在新函数内部。

新函数的参数可以根据原有函数的参数来定义,通常使用*args和**kwargs表示任意数量的位置参数和关键字参数。

最后,装饰器函数要返回新函数wrapper。

下面我们来看一个具体的例子。

def log(func):

    def wrapper(*args, **kwargs):

        print(f"Calling function {func.__name__}")

        return func(*args, **kwargs)

    return wrapper

@log

def add(a, b):

    return a + b

使用@log装饰器来给add函数添加打印日志的功能。当我们调用add函数时,会自动打印出函数名。

add(1, 2)

# Output: Calling function add

装饰器函数可以添加多个装饰器,多个装饰器按照从上到下的顺序依次执行。

例如,我们可以添加一个计时器装饰器:

import time

def timer(func):

    def wrapper(*args, **kwargs):

        start_time = time.time()

        result = func(*args, **kwargs)

        end_time = time.time()

        print(f"Function {func.__name__} elapsed time: {end_time - start_time}s")

        return result

    return wrapper

@log

@timer

def add(a, b):

    return a + b

使用@log和@timer装饰器来给add函数添加打印日志和计时的功能。当我们调用add函数时,会自动打印出函数名和运行时间。

add(1, 2)

# Output: 

# Calling function add

# Function add elapsed time: 1.2e-05s

装饰器还可以接受参数,通过在装饰器函数之上再定义一个函数来接收参数,并返回一个装饰器函数。

例如,我们可以定义一个带有参数的装饰器函数,用于指定需要打印的日志级别:

def log(level):

    def decorator(func):

        def wrapper(*args, **kwargs):

            print(f"[{level}] Calling function {func.__name__}")

            return func(*args, **kwargs)

        return wrapper

    return decorator

@log("INFO")

def add(a, b):

    return a + b

使用@log("INFO")装饰器来给add函数添加打印INFO级别的日志。当我们调用add函数时,会自动打印出INFO级别的日志。

add(1, 2)

# Output: [INFO] Calling function add

最后,装饰器还可以用于类。同样的语法,在类的定义之前加上一个@符号,后面紧跟着装饰器函数的名称。

例如,我们可以定义一个用于验证用户权限的装饰器:

def access_control(func):

    def wrapper(self, *args, **kwargs):

        if self.logged_in:

            return func(self, *args, **kwargs)

        else:

            raise Exception("Access denied")

    return wrapper

class Calculator:

    def __init__(self):

        self.logged_in = False

    

    @access_control

    def add(self, a, b):

        return a + b

使用@access_control装饰器来给add方法添加权限验证的功能。当我们调用add方法时,会先检查用户是否已登录,如果已登录则执行原有的add方法,否则抛出异常。

calculator = Calculator()

calculator.logged_in = True

calculator.add(1, 2)

# Output: 3

装饰器是Python中非常有用的特性,可以帮助我们在不修改原有代码的情况下添加功能。通过使用装饰器,我们可以实现代码的复用和组合,提高代码的可读性和可维护性。