类中定义的方法作为装饰器

方法怎么当装饰器用?看完这篇你就懂了 🚀

大家平时用装饰器,基本都是定义普通函数。其实,类里面定义的方法也能当装饰器用!今天就来聊聊这个骚操作,顺便看看它一般在哪些场景下会派上用场。

先来一个最简单的例子 🌰

class DecoratorClass:
    def my_decorator(self, func):
        def wrapper(*args, **kwargs):
            print(f"Before calling {func.__name__}")
            result = func(*args, **kwargs)
            print(f"After calling {func.__name__}")
            return result
        return wrapper

# 注意:得先创建类的实例
decorator_instance = DecoratorClass()

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

say_hello()

运行结果:

Before calling say_hello
Hello!
After calling say_hello

✅ 关键点:这里用的是 实例方法 作为装饰器,所以必须先 new 一个对象出来。


⚠️ 有几个坑需要提前知道

1️⃣ 实例方法必须绑定实例

不能直接写 @DecoratorClass.my_decorator,因为那样会把 self 搞丢。必须像下面这样:

class Logger:
    def log(self, func):
        def wrapper(*args, **kwargs):
            print(f"Logging: {func.__name__} called")
            return func(*args, **kwargs)
        return wrapper

logger = Logger()  # 👈 先创建实例

@logger.log  # 👈 用实例的方法来装饰
def my_function():
    pass

2️⃣ 类方法(classmethod)和静态方法(staticmethod)也可以

class Decorators:
    @classmethod
    def class_decorator(cls, func):
        def wrapper(*args, **kwargs):
            print(f"Class decorator from {cls.__name__}")
            return func(*args, **kwargs)
        return wrapper
    
    @staticmethod
    def static_decorator(func):
        def wrapper(*args, **kwargs):
            print("Static decorator")
            return func(*args, **kwargs)
        return wrapper

@Decorators.class_decorator   # 直接通过类名调用
def func1():
    pass

@Decorators.static_decorator
def func2():
    pass

3️⃣ 装饰类内部的方法(self 怎么传?)

如果装饰器要用来装饰 同一个类里的其他方法,那就要小心处理 self

class Validator:
    def validate_positive(self, func):
        def wrapper(instance, value):  # 👈 instance 就是被装饰方法的 self
            if value < 0:
                raise ValueError("Value must be positive")
            return func(instance, value)
        return wrapper

class BankAccount:
    def __init__(self):
        self.balance = 0
    
    @Validator().validate_positive  # 👈 还是得先有实例
    def deposit(self, amount):
        self.balance += amount
        return self.balance

account = BankAccount()
account.deposit(100)  # 正常
# account.deposit(-50)  # 会抛出 ValueError

💡 一般用在哪些场景?

🔁 注册模式(Registry Pattern)

class EventHandler:
    def __init__(self):
        self.handlers = {}
    
    def on(self, event_name):
        def decorator(func):
            self.handlers[event_name] = func
            return func
        return decorator

handler = EventHandler()

@handler.on("click")
def handle_click():
    print("Clicked!")

@handler.on("hover")
def handle_hover():
    print("Hovering!")

这种写法在事件系统、插件注册、回调管理里非常常见。


🧠 总结一下

类型能否当装饰器注意事项
实例方法✅ 能需要先创建实例
类方法✅ 能直接用类名调用
静态方法✅ 能直接用类名调用

优点

  • 实例方法可以访问 self,因此可以做成有状态的装饰器(比如记录调用次数、保存配置等)。
  • 适合做注册中心、校验器、日志记录、依赖注入等。

缺点(或者说需要注意的地方)

  • 大部分情况下,你必须在装饰之前就拿到类的实例。
  • 这意味着装饰器的配置是在运行时发生的,而不是在类定义时就固定下来。

总之,类方法作为装饰器是一种高级但很有用的技巧,掌握了它,你的代码会更优雅、更灵活。如果你用过 Flask 的路由装饰器,其实原理也差不多~ 😎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值