python装饰器的简单理解

发布于:2025-05-25 ⋅ 阅读:(23) ⋅ 点赞:(0)

python装饰器可分为函数装饰器和类装饰器,在理解过程中,可以认为是相同的。

一、不带参数的函数装饰器

def my_decorator(func):
    def wrapper():
        print("函数执行前")
        func()
        print("函数执行后")
    return wrapper

这里my_decorator就是我们定义的一个不带参数的装饰器(其本身就是一个函数),

使用如下:

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

上述代码段可以简单的理解为say_hello=my_decorator(say_hello),即将say_hello函数作为参数传递给装饰器函数,并返回装饰器函数中定义的函数名。因此,say_hello=wrapper

当我们执行say_hello()时,相当于执行wrapper()
执行结果如下:

say_hello()

输出:
复制函数执行前
Hello!
函数执行后

二、带参数的函数装饰器

定义带参数的函数装饰器

def repeat(num_times):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(num_times):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

使用如下:

@repeat(3)
def greet(name):
    print(f"Hello, {name}!")

这里,@repeat(3)相当于@decorator(可以简单的理解为,先将参数传递给外部装饰器repeat,然后返回真正的装饰器decorator)
因此 上述代码可以看做greet=decorator(greet)greet = wrapper 只是相比于不带参数的装饰器多传递了一个参数。

当我们执行greet()时,同样相当于执行wrapper()
执行实例如下:

greet("Alice")
输出:
Hello, Alice!
Hello, Alice!
Hello, Alice!

三、类装饰器

定义类装饰器

class MyDecorator:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print("函数执行前")
        result = self.func(*args, **kwargs)
        print("函数执行后")
        return result

调用如下:

@MyDecorator
def say_hello():
    print("Hello!")

上述代码可以直接理解为say_hello = MyDecorator(say_hello) 因此,当使用say_hello()时,相当于直接调用__call__()函数

执行实例如下:

say_hello()

输出:
函数执行前
Hello!
函数执行后

四、装饰器作用于类定义

定义装饰器:

def add_class_name(cls):
    # 在类上添加一个属性,并返回原类
    cls.class_name = 'person class'
    return cls

调用如下:

@add_class_name          
class Person:
    def __init__(self, name):
        self.name = name

上述代码可以等价于Person = add_class_name(Person),那么此时调用Person就相当于调用add_class_name(Person)

执行实例

A = Person()

上面这行代码相当于在运行A = add_class_name( Person)运行的结果,就是返回了一个被装饰过的新的cls,因此新的cls有了新的属性class_name,我们就可以调用 print(A.class_name) # 输出: "person class"

五、 装饰器的作用

个人理解:

  1. 增加代码复用:装饰器中封装一些通用的功能,定义不同函数时都可以利用装饰器中的功能。(固定装饰器,原函数不固定);
  2. 为原函数拓展功能:不改动原函数中的代码,例如:第一节中的say_hello()函数作为无法改动的原函数,那么我们可以通过改动装饰器中的功能,为原函数添加拓展功能(固定原函数,改动装饰器);

六、应用场景

Python 中装饰器的应用场景主要用于代码复用逻辑抽离横切关注点(如日志、验证、缓存、安全控制等)。下面是一些典型应用场景和具体示例:


6.1 日志记录(Logging)

用途:记录函数或方法的调用行为,便于调试和分析。

def log(func):
    def wrapper(*args, **kwargs):
        print(f"[LOG] Calling {func.__name__} with args={args}, kwargs={kwargs}")
        result = func(*args, **kwargs)
        print(f"[LOG] {func.__name__} returned {result}")
        return result
    return wrapper

@log
def add(a, b):
    return a + b

add(2, 3)

6.2. 权限验证(Authentication/Authorization)

用途:用于 Web 应用、命令行工具中限制某些函数的访问。

def require_admin(func):
    def wrapper(user, *args, **kwargs):
        if not user.get("is_admin"):
            raise PermissionError("You must be an admin.")
        return func(user, *args, **kwargs)
    return wrapper

@require_admin
def delete_user(user, user_id):
    print(f"Deleting user {user_id}")

6.3. 函数缓存(Memoization)

用途:缓存计算结果,加速函数响应,避免重复计算。

from functools import lru_cache

@lru_cache(maxsize=128)
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n - 1) + fibonacci(n - 2)

print(fibonacci(40))  # 快速返回

6.4. 性能计时(Profiling)

用途:度量函数执行时间,用于性能分析。

import time

def timer(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)
        end = time.time()
        print(f"{func.__name__} took {end - start:.4f}s")
        return res
    return wrapper

@timer
def slow_function():
    time.sleep(1)
    return "Done"

slow_function()

6.5. 类注册与插件机制

用途:动态注册类或函数用于工厂、插件系统。

registry = {}

def register(name):
    def decorator(cls):
        registry[name] = cls
        return cls
    return decorator

@register("dog")
class Dog:
    def speak(self):
        return "Woof"

print(registry["dog"]().speak())  # 输出 "Woof"

6.6. 输入验证 / 参数检查

用途:自动检查输入是否符合预期。

def validate_non_negative(func):
    def wrapper(x):
        if x < 0:
            raise ValueError("Negative value not allowed")
        return func(x)
    return wrapper

@validate_non_negative
def sqrt(x):
    return x ** 0.5

6.7. 类装饰器(用于元编程、修改类行为)

用途:为类增加静态属性、方法、注册机制等。

def add_repr(cls):
    def __repr__(self):
        return f"{cls.__name__}({self.__dict__})"
    cls.__repr__ = __repr__
    return cls

@add_repr
class Person:
    def __init__(self, name):
        self.name = name

print(Person("Alice"))

网站公告

今日签到

点亮在社区的每一天
去签到