• Python 如何使用装饰器(decorators)


    1. 装饰器的基本概念

    装饰器是一个函数,它接受一个函数作为参数,并返回一个新的函数。装饰器可以用于在函数调用前后添加额外的功能,或者修改函数的行为。

    装饰器通常通过在函数定义前使用@decorator_name语法来应用。

    1. def decorator(func):
    2. def wrapper():
    3. print("Something is happening before the function is called.")
    4. func()
    5. print("Something is happening after the function is called.")
    6. return wrapper
    7. @decorator
    8. def say_hello():
    9. print("Hello!")
    10. say_hello()

    输出结果:

    1. Something is happening before the function is called.
    2. Hello!
    3. Something is happening after the function is called.

    2. 创建和使用简单装饰器

    定义装饰器

    一个简单的装饰器如下:

    1. def my_decorator(func):
    2. def wrapper():
    3. print("Something is happening before the function is called.")
    4. func()
    5. print("Something is happening after the function is called.")
    6. return wrapper

    这个装饰器函数my_decorator接受一个函数func作为参数,并返回一个包装函数wrapper。在包装函数中,首先打印一条消息,然后调用传入的函数,最后再打印一条消息。

    使用装饰器

    可以使用@my_decorator语法来应用这个装饰器:

    1. @my_decorator
    2. def say_hello():
    3. print("Hello!")
    4. say_hello()

    这等价于:

    1. def say_hello():
    2. print("Hello!")
    3. say_hello = my_decorator(say_hello)
    4. say_hello()

    3. 装饰器的嵌套

    可以将多个装饰器应用于同一个函数,这称为装饰器的嵌套。装饰器的应用顺序是自下而上的,即最内层的装饰器最先应用。

    1. def decorator1(func):
    2. def wrapper():
    3. print("Decorator 1")
    4. func()
    5. return wrapper
    6. def decorator2(func):
    7. def wrapper():
    8. print("Decorator 2")
    9. func()
    10. return wrapper
    11. @decorator1
    12. @decorator2
    13. def say_hello():
    14. print("Hello!")
    15. say_hello()

    输出结果:

    1. Decorator 1
    2. Decorator 2
    3. Hello!

    4. 带参数的装饰器

    装饰器本身也可以接受参数。为了实现这一点,我们需要再嵌套一层函数。

    创建带参数的装饰器

    1. def repeat(num):
    2. def decorator(func):
    3. def wrapper(*args, **kwargs):
    4. for _ in range(num):
    5. func(*args, **kwargs)
    6. return wrapper
    7. return decorator

    使用带参数的装饰器

    可以传递参数来控制装饰器的行为:

    1. @repeat(3)
    2. def say_hello():
    3. print("Hello!")
    4. say_hello()

    输出结果:

    1. Hello!
    2. Hello!
    3. Hello!

    5. 类装饰器

    除了函数装饰器,Python还支持类装饰器。类装饰器是一个实现了__call__方法的类,这样的类可以像函数一样调用。

    创建类装饰器

    1. class MyDecorator:
    2. def __init__(self, func):
    3. self.func = func
    4. def __call__(self, *args, **kwargs):
    5. print("Something is happening before the function is called.")
    6. self.func(*args, **kwargs)
    7. print("Something is happening after the function is called.")

    使用类装饰器

    1. @MyDecorator
    2. def say_hello():
    3. print("Hello!")
    4. say_hello()

    输出结果:

    1. Something is happening before the function is called.
    2. Hello!
    3. Something is happening after the function is called.

    6. 内置装饰器

    Python提供了一些内置的装饰器,如@staticmethod@classmethod@property。这些装饰器常用于类的方法定义。

    @staticmethod

    @staticmethod用于定义静态方法,静态方法不需要访问类或实例的属性和方法。

    1. class MyClass:
    2. @staticmethod
    3. def static_method():
    4. print("This is a static method.")
    5. MyClass.static_method()

    @classmethod

    @classmethod用于定义类方法,类方法的第一个参数是类本身(通常命名为cls)。

    1. class MyClass:
    2. @classmethod
    3. def class_method(cls):
    4. print(f"This is a class method of {cls}.")
    5. MyClass.class_method()

    @property

    @property用于将方法转换为属性,以便通过属性访问方法的结果。

    1. class MyClass:
    2. def __init__(self, value):
    3. self._value = value
    4. @property
    5. def value(self):
    6. return self._value
    7. @value.setter
    8. def value(self, value):
    9. self._value = value
    10. obj = MyClass(42)
    11. print(obj.value) # 输出: 42
    12. obj.value = 99
    13. print(obj.value) # 输出: 99

    7. 装饰器的实际应用场景

    装饰器在实际编程中有很多应用场景,下面我们列举一些常见的例子。

    日志记录

    装饰器可以用于记录函数的调用情况。

    1. def log(func):
    2. def wrapper(*args, **kwargs):
    3. print(f"Calling function {func.__name__}")
    4. result = func(*args, **kwargs)
    5. print(f"Function {func.__name__} finished")
    6. return result
    7. return wrapper
    8. @log
    9. def say_hello():
    10. print("Hello!")
    11. say_hello()

    输出结果:

    1. Calling function say_hello
    2. Hello!
    3. Function say_hello finished

    权限检查

    装饰器可以用于检查用户是否有权限执行某个操作。

    1. def requires_permission(permission):
    2. def decorator(func):
    3. def wrapper(user, *args, **kwargs):
    4. if user.has_permission(permission):
    5. return func(user, *args, **kwargs)
    6. else:
    7. print(f"User {user.name} does not have {permission} permission.")
    8. return wrapper
    9. return decorator
    10. class User:
    11. def __init__(self, name, permissions):
    12. self.name = name
    13. self.permissions = permissions
    14. def has_permission(self, permission):
    15. return permission in self.permissions
    16. @requires_permission("admin")
    17. def delete_user(user):
    18. print(f"User {user.name} deleted.")
    19. admin_user = User("Admin", ["admin"])
    20. normal_user = User("User", [])
    21. delete_user(admin_user) # 输出: User Admin deleted.
    22. delete_user(normal_user) # 输出: User User does not have admin permission.

    缓存

    装饰器可以用于缓存函数的返回结果,以提高性能。

    1. def cache(func):
    2. memo = {}
    3. def wrapper(*args):
    4. if args in memo:
    5. return memo[args]
    6. result = func(*args)
    7. memo[args] = result
    8. return result
    9. return wrapper
    10. @cache
    11. def fibonacci(n):
    12. if n < 2:
    13. return n
    14. return fibonacci(n-1) + fibonacci(n-2)
    15. print(fibonacci(30)) # 输出: 832040

    计时

    装饰器可以用于测量函数的执行时间。

    1. import time
    2. def timer(func):
    3. def wrapper(*args, **kwargs):
    4. start_time = time.time()
    5. result = func(*args, **kwargs)
    6. end_time = time.time()
    7. print(f"Function {func.__name__} took {end_time - start_time:.4f} seconds")
    8. return result
    9. return wrapper
    10. @timer
    11. def long_running_function():
    12. time.sleep(2)
    13. long_running_function() # 输出: Function long_running_function took 2.0001 seconds

    参数校验

    装饰器可以用于验证函数参数的有效性。

    1. def validate_args(func):
    2. def wrapper(*args, **kwargs):
    3. if any(arg < 0 for arg in args):
    4. raise ValueError("Arguments must be non-negative")
    5. return func(*args, **kwargs)
    6. return wrapper
    7. @validate_args
    8. def add(a, b):
    9. return a + b
    10. print(add(3, 5)) # 输出: 8
    11. # print(add(-1, 5)) # 抛出异常: ValueError: Arguments must be non-negative

  • 相关阅读:
    @Tag和@Operation标签失效问题。SpringDoc 2.2.0(OpenApi 3)和Spring Boot 3.1.1集成
    《UnityShader入门精要》学习2
    编程之美1 让CPU占用率曲线听你指挥
    [Bug]Ubuntu下使用TexStudio存在的一些问题
    初始Cpp之 五、函数
    seata-server-1.5.2的部署
    21JVM-类加载和垃圾回收算法
    [最短路]猛犸不上 Ban 2021RoboCom决赛D
    java数据库linux面试(详细)
    多图看懂Java虚拟机,JVM相关面试常考点全在这里了
  • 原文地址:https://blog.csdn.net/Itmastergo/article/details/140461995