装饰器和类/实例方法

问题描述 投票:0回答:1

我有一个类,可以在事件发生时将数据预加载到缓存中。我想使用装饰器和事件键注册加载器函数,以便当事件触发时,我可以执行这些函数。

from collections import defaultdict

class Preloader:
    def __init__(self):
        self.events = defaultdict(set)

    def register(self, event_key: str):
        print(f"Registering event: `{event_key}`")

        def decorator(func):
            print("Decorating function: ", func.__qualname__)

            def wrapper(*args, **kwargs):
                print("Wrapper called...")
                # call func, add results to cache, return results
                return func(*args, **kwargs)

            self.events[event_key].add(wrapper)
            return wrapper

        return decorator

    def preload(self, event_key: str, *args, **kwargs):
        for func in self.events[event_key]:
            func(*args, **kwargs)

然后我用

register
方法装饰函数。

preloader = Preloader()

class Product:

    @staticmethod
    @preloader.register("products")
    def get_products_static():
        # there would really be a database call here
        print("Getting products from static method...")

    @classmethod
    @preloader.register("products")
    def get_products_cls(cls):
        # there would really be a database call here
        print("Getting products from class method...")

当我调用

preloader.preload('products')
时,类方法调用失败并显示

TypeError: Product.get_products_cls() missing 1 required positional argument: 'cls'

如何修改我的装饰器以接受类和实例方法?

python decorator python-decorators
1个回答
0
投票

选择类/实例的功能怎么样

def preload(self, event_key: str, *args, **kwargs):
for func in self.events[event_key]:
    # Check if the function is a class method or instance method
    if isinstance(func, types.MethodType):  # Check if it's a method
        # Rebind 'self' or 'cls' if needed when invoking the function
        bound_func = types.MethodType(func.__func__, args[0])
        bound_func(*args, **kwargs)
    else:
        # Directly call the function if it's static
        func(*args, **kwargs)
© www.soinside.com 2019 - 2024. All rights reserved.