目录

python注解与装饰器

目录

背景

python想要使用注解,来实现一些方便解耦合的功能。

例如对某个flask的路由函数加入token验证功能。但是又不是针对所有的函数都加入。

原理

实际上就是闭包,外面的decorator函数,是为了将目标函数封装到里面的闭包函数里面去。

只有在@decorator的时候,会去执行这个decorator函数,

每次使用目标函数,实际上就是使用wrapper函数(目标函数是封装在wrapper函数里面的)

demo

装饰器是 Python 中一种强大的语法特性,用于修改或扩展函数或类的行为。它们是一种函数,可以接受另一个函数(或类)作为参数,并返回一个新的函数(或类)。装饰器在代码中以 @decorator_name 的形式应用于目标函数或方法,以实现在目标函数执行前后添加额外的逻辑。

以下是装饰器的基本使用示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("Something is happening before the function is called.")
        result = func(*args, **kwargs)  # 调用原始函数并传递参数
        print("Something is happening after the function is called.")
        return result
    return wrapper

@my_decorator
def greet(name):
    print("somthing is happening in greet function")
    return f"Hello, {name}!"

greeting = greet("Alice")
print(greeting)

在这个示例中,my_decorator 是一个装饰器函数,它接受一个函数 func 作为参数。它定义了一个内部函数 wrapper,在调用目标函数 func 前后添加了额外的逻辑。

然后,我们将 @my_decorator 应用于 say_hello 函数,这等效于执行 say_hello = my_decorator(say_hello),从而将 say_hello 函数传递给 my_decorator 并重新赋值为装饰后的函数。

装饰器的原理:

  1. 定义装饰器函数:装饰器函数接受一个函数(或类)作为参数,并返回一个新的函数(或类)。这个新函数通常包含了在原始函数执行前后添加的逻辑。
  2. 应用装饰器:通过在目标函数(或类)之前加上 @decorator_name,将装饰器应用于目标函数。这等效于调用装饰器函数并将目标函数作为参数传递给它,然后用装饰器返回的新函数替代原始函数。
  3. 调用装饰后的函数:当调用经过装饰的函数时,实际上是调用了装饰器返回的新函数。这个新函数在调用目标函数前后执行了额外的逻辑。

装饰器的应用场景包括:日志记录、权限验证、性能分析、输入校验等。它们能够在不修改原始函数代码的情况下,实现对函数行为的定制和扩展。

verify token flask

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 用于验证请求的token的装饰器
def verify_request_token(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        token = None
        if request.method == 'GET':
            # 获取请求参数中的token
            token = request.args.get('token')
        elif request.method == 'POST':
            # 获取请求参数中的token
            token = request.data.get('token')


        if token:
            conf = get_config()
            conf_token = conf["secrets"]['token']
            if token != conf_token:
                return Kit.common_rsp(data="token error", status="Forbidden")
        else:
            return Kit.common_rsp(data="token error", status="Forbidden")
        
        return func(*args, **kwargs)
    return wrapper

带参数的注解写法(二层闭包)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
def my_decorator_with_args(arg1, arg2):
    def decorator(func):
        def wrapper():
            print(f"Something is happening before the function is called. Arg1: {arg1}, Arg2: {arg2}")
            func()
            print("Something is happening after the function is called.")
        return wrapper
    return decorator

@my_decorator_with_args("Hello", "World")
def say_hello():
    print("Hello!")

say_hello()

ref

浅谈java中注解和python中装饰器的区别