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

Python中的装饰器函数详解和用法

发布时间:2023-06-24 12:53:04

装饰器(Decorator)是 Python 中一个非常重要的语法特性,它可以在不改变原有函数代码的基础上,对函数进行增强或者添加额外的逻辑,同时也可以用来对函数进行统计、日志记录等操作,极大地提高了编程的灵活性和可维护性。

装饰器函数是一种特殊的函数,它的参数是一个函数对象或者是一个可调用对象,它的返回值也是一个函数对象。通过装饰器函数可以在函数执行前后进行一些额外的操作,例如计算函数执行时间,检查函数参数或者返回值等。

下面我们来看一个简单的实例,使用装饰器函数计算函数执行时间:

import time

def time_it(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print("Function {} execution time: {}".format(func.__name__, end-start))
        return result
    
    return wrapper

@time_it
def factorial(n):
    """
    计算阶乘
    """
    if n == 0:
        return 1
    else:
        return n * factorial(n-1)

factorial(5)

在上面的代码中,我们定义了一个名为 time_it 的装饰器函数,它的参数是一个函数 func。在函数内部定义了名为 wrapper 的函数,它接收任意数量和类型的参数和关键字参数,调用 func 并记录了函数的开始时间和结束时间,并输出函数的执行时间。

在进行阶乘运算时,在函数定义前面加上 @time_it 装饰器即可在执行阶乘函数时自动执行装饰器函数。

除了计算执行时间外,我们还可以使用装饰器函数来完成一些其他的任务,例如:

### 1. 记录日志

使用装饰器函数来记录函数的调用次数及参数信息。

def log_it(func):
    count = 0
    def wrapper(*args, **kwargs):
        nonlocal count
        count += 1
        print("Calling function {}: count={}, args={}, kwargs={}".format(func.__name__, count, args, kwargs))
        return func(*args, **kwargs)
    return wrapper

@log_it
def add_numbers(a, b):
    """
    计算两个数的和
    """
    return a + b

add_numbers(2, 3)
add_numbers(4, 5)

### 2. 检查函数参数和返回值

如果要对函数的参数和返回值进行检查,则可以编写一个装饰器函数来实现。

def check_input_output(func):
    def wrapper(*args, **kwargs):
        for arg in args:
            if not isinstance(arg, int):
                raise TypeError("Argument {} is not an integer.".format(arg))
        result = func(*args, **kwargs)
        if not isinstance(result, int):
            raise TypeError("Result {} is not an integer.".format(result))
        return result
    return wrapper

@check_input_output
def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n-1)

factorial("5")

### 3. 缓存函数结果

如果一个函数的输入输出相同,那么它的输出结果也应该是相同的。因此,我们可以使用装饰器函数来缓存函数的结果,从而避免执行重复计算。

def memoize(func):
    cache = {}
    def wrapper(*args):
        if args in cache:
            return cache[args]
        else:
            result = func(*args)
            cache[args] = result
            return result
    return wrapper

@memoize
def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n-1)

factorial(4)

在上面的例子中,我们定义了一个名为 memoize 的装饰器函数,使用字典来缓存函数的执行结果,从而避免重复计算。

总结一下,通过装饰器函数可以在函数执行前后进行一些额外的操作,例如计算函数执行时间、记录函数调用次数和参数、缓存函数执行结果等。使用装饰器函数可以避免在每个函数中都编写重复的代码,并提高了代码的复用性和可维护性。在 Python 中有很多方便好用的内置装饰器,例如 @classmethod、@staticmethod、@property 等,这些装饰器函数可以让代码更加简洁和易于理解。