Python 高阶函数的装饰器

  • Post category:Python

下面详细讲解Python高阶函数的装饰器使用方法的完整攻略。

什么是高阶函数

在 Python 中,函数本身也是对象,这使得我们可以将其作为参数进行传递或将函数的返回值分配给另一个变量。这种将函数用作参数或返回值的函数称为”高阶函数”。

什么是装饰器

装饰器是 Python 中的一种函数,它用于在不修改原函数代码的情况下,向原函数添加新的功能。

装饰器的使用方法

装饰器使用 ” @ ” 符号,紧接着是装饰器名称,既可以作用于普通函数,也可以作用于类的方法。

下面是一个示例:

def my_decorator(func):
    def wrapper():
        print("Something is happening before the function is called.")
        func()
        print("Something is happening after the function is called.")
    return wrapper

@my_decorator
def say_hello():
    print("Hello World!")

say_hello()

在上面的示例中,my_decorator 是一个装饰器函数,它封装了一个 wrapper 函数,用于添加额外的功能。在 say_hello 函数的定义之前,我们使用 @my_decorator 表示以下的 say_hello 函数应该被 my_decorator 所装饰。当我们最终执行 say_hello() 时,实际调用的是 wrapper() 函数,从而达到了通过装饰器为函数添加新功能的目的。

装饰器的原理

装饰器的原理比较简单,就是使用闭包和函数作为参数传递。现在我们来分别对装饰器的原理进行解释。

闭包

在 Python 中,闭包需要满足以下两个条件:

  1. 其中内部函数引用外部变量。
  2. 其外层函数返回内部函数。

示例:

def outer_func(x):
    def inner_func(y):
        return x + y
    return inner_func

add_10 = outer_func(10)

print(add_10(5)) # Output: 15

在上面的示例中,outer_func 返回的是一个内部函数 inner_func,它引用了外部函数 outer_func 的变量 x。我们使用 add_10 表示其中的 outer_func(10),然后调用 add_10(5) 实际上是在调用 inner_func,从而实现了闭包。

函数作为参数传递

在 Python 中,函数可以作为参数传递,这是 Python 作为高阶函数语言的一个特性。

示例:

def add(x, y):
    return x + y

def sub(x, y):
    return x - y

def calculate(func, x, y):
    return func(x, y)

print(calculate(add, 5, 3)) # Output: 8
print(calculate(sub, 5, 3)) # Output: 2

在上面的示例中,calculate 函数接收了一个函数 func 作为参数,并对其进行调用。当我们调用 calculate(add, 5, 3) 时,实际上是在调用 add(5, 3),从而实现了参数传递。

综合闭包和函数作为参数的特性,就实现了 Python 装饰器的原理。

装饰器的使用场景

  1. 给函数增加日志、计时等操作。
  2. 给函数增加缓存等操作。
  3. 给函数增加权限、验证等操作。
  4. 给函数增加重试、失败重连等操作。

让我们来看两个具体的示例

示例一:计时装饰器

import time

def time_it(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(func.__name__, "耗时:", end - start, "秒")
        return result
    return wrapper

@time_it
def add(x, y):
    time.sleep(1)
    return x + y

print(add(10, 20))

在上面的示例中,我们定义了一个 time_it 装饰器,它会在程序调用被装饰的函数时,记录当前的时间戳,并在函数执行结束后,计算执行时间并输出。在 add 函数被调用时,实际上调用的是 time_it(add),从而实现了计时功能。

示例二:权限装饰器

def is_admin(func):
    def wrapper(*args, **kwargs):
        if kwargs.get("user") != "admin":
            raise Exception("You are not allowed to access this resource.")
        return func(*args, **kwargs)
    return wrapper

@is_admin
def delete_record(id, user):
    print("Record with ID:", id, "deleted successfully.")

delete_record(id=100, user="admin")

在上面的示例中,我们定义了一个 is_admin 装饰器,它作为 delete_record 函数的装饰器,可以根据传入的 user 参数来检查用户是否具备删除记录的权限。如果检查不通过,则会抛出异常提示。

总结

装饰器是 Python 语言中很重要的一种机制,它可以让我们在不修改原代码的情况下为函数添加新的功能操作。掌握好装饰器的使用方法和原理,将有助于我们更好地理解 Python 语言的特性和机制。