Python 中的装饰器如何工作?

开发 前端
装饰器(Decorator)是 Python 中一种高级特性,它允许程序员修改或增强函数和方法的行为,而无需直接更改其源代码。

装饰器(Decorator)是 Python 中一种高级特性,它允许程序员修改或增强函数和方法的行为,而无需直接更改其源代码。装饰器本质上是一个返回函数的高阶函数,它可以接收一个函数作为参数,并返回一个新的或修改后的函数。通过使用装饰器,您可以实现诸如日志记录、访问控制、性能测量等功能,同时保持代码的清晰和模块化。

装饰器的工作原理

装饰器定义:首先,您需要定义一个装饰器函数。这个函数接受一个被装饰的函数作为参数,并返回一个新的函数(通常是内部定义的一个闭包),该新函数可以在执行原始函数之前或之后添加额外逻辑。

应用装饰器:要将装饰器应用于某个函数,可以使用 @decorator_name 语法糖,放在函数定义之前。这相当于在函数定义后立即调用装饰器并将函数作为参数传递给它。

执行流程:当调用被装饰的函数时,实际上是在调用装饰器返回的新函数。这意味着您可以在实际执行目标函数之前或之后插入自定义行为。

示例:基本装饰器

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!")
say_hello()
# 输出:
# Something is happening before the function is called.
# Hello!
# Something is happening after the function is called.
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

在这个例子中,my_decorator 是一个简单的装饰器,它包装了 say_hello 函数,在调用前后打印消息。

带参数的装饰器

有时,您可能希望装饰器本身也能接受参数。为了实现这一点,可以创建一个“装饰器工厂”——即一个返回装饰器的函数。

示例:带参数的装饰器

def repeat(num_times):
    def decorator_repeat(func):
        def wrapper(*args, **kwargs):
            for _ in range(num_times):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator_repeat
@repeat(num_times=3)
def greet(name):
    print(f"Hello {name}")
greet("Alice")
# 输出:
# Hello Alice
# Hello Alice
# Hello Alice
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.

这里,repeat 是一个装饰器工厂,它根据提供的 num_times 参数生成一个具体的装饰器。

类装饰器

除了函数,Python 还支持类装饰器。类装饰器通常用于修改类的行为或属性。它们接收类作为参数,并返回一个新的类或修改后的类。

示例:类装饰器

def add_method(cls):
    def decorator(func):
        setattr(cls, func.__name__, func)
        return cls
    return decorator
@add_method
class MyClass:
    pass
@add_method(MyClass)
def new_method(self):
    print("This is a dynamically added method.")
obj = MyClass()
obj.new_method()  # 输出: This is a dynamically added method.
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

在这个例子中,add_method 是一个类装饰器,它向 MyClass 动态添加了一个新的方法。

内置装饰器

Python 提供了一些内置的装饰器来简化常见的编程任务:

@classmethod 和 @staticmethod:用于定义类方法和静态方法。

@property:用于将类的方法转换为只读属性。

@functools.lru_cache:用于缓存函数的结果以提高性能。

@dataclasses.dataclass:用于自动为类生成特殊方法(如 __init__() 和 __repr__())。

示例:使用 @property

class Circle:
    def __init__(self, radius):
        self._radius = radius
    @property
    def radius(self):
        """The radius property."""
        print("Getting radius")
        return self._radius
    @radius.setter
    def radius(self, value):
        if value >= 0:
            self._radius = value
        else:
            raise ValueError("Radius must be non-negative")
circle = Circle(5)
print(circle.radius)  # 输出: Getting radius\n5
circle.radius = 10
print(circle.radius)  # 输出: Getting radius\n10
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

使用多个装饰器

如果一个函数被多个装饰器修饰,则这些装饰器按照从下到上的顺序依次应用。也就是说,最接近函数定义的装饰器最先执行。

示例:多个装饰器

def decorator_one(func):
    def wrapper():
        print("Decorator one")
        func()
    return wrapper
def decorator_two(func):
    def wrapper():
        print("Decorator two")
        func()
    return wrapper
@decorator_one
@decorator_two
def hello():
    print("Hello!")
hello()
# 输出:
# Decorator one
# Decorator two
# Hello!
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.

在这个例子中,decorator_two 首先被应用,然后是 decorator_one。

总结

装饰器是 Python 中非常强大且灵活的工具,它们可以让您以优雅的方式扩展或修改函数和类的功能。通过理解装饰器的工作原理以及如何构建自己的装饰器,您可以编写出更加简洁、可维护和功能丰富的代码。随着经验的积累,您还将发现更多关于装饰器的高级用法和最佳实践。

责任编辑:华轩 来源: 测试开发学习交流
相关推荐

2010-02-01 17:50:32

Python装饰器

2022-09-19 23:04:08

Python装饰器语言

2021-04-11 08:21:20

Python@property装饰器

2016-11-01 09:24:38

Python装饰器

2021-06-03 09:18:25

装饰器模式包装

2023-02-07 07:47:52

Python装饰器函数

2024-05-24 11:36:28

Python装饰器

2022-09-14 08:16:48

装饰器模式对象

2021-06-14 09:25:20

PythonPython 3.9编程语言

2024-09-12 15:32:35

装饰器Python

2021-07-27 15:58:12

Python日志代码

2024-11-04 15:30:43

Python装饰器函数

2021-06-01 07:19:58

Python函数装饰器

2025-04-14 08:35:00

Python类装饰器装饰器

2022-09-27 11:01:08

Python装饰器

2023-12-11 15:51:00

Python装饰器代码

2024-05-10 12:33:06

flask装饰器

2022-05-10 09:12:16

TypeScript装饰器

2022-09-21 09:04:07

Python装饰器

2023-12-13 13:28:16

装饰器模式Python设计模式
点赞
收藏

51CTO技术栈公众号