Python decorator来确定方法的执行顺序

2024-06-23 19:36:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个基本类Framework,有3个用户可以设置的方法:initializehandle_event和{}。在

这些方法由run方法执行:

class Framework(object):

    def initialize(self):
        pass

    def handle_event(self, event):
        pass

    def finalize(self):
        pass 

    def run(self):
        self.initialize()

        for event in range(10):
            self.handle_event(event)

        self.finalize()

{{cd6>这样{cd6>就可以创建 ^{pr2}$

这些修饰符决定了用户可以添加到类中的可选方法的执行顺序。我认为默认情况下,initializehandle_event和{}应该取precedence=0。然后,用户可以添加任何具有正确装饰器的方法,他将知道这些方法在模拟运行中何时执行。在

老实说,我不知道如何着手解决这个问题。任何能把我推向正确方向的帮助都是非常欢迎的!非常感谢。在


Tags: 方法run用户selfeventforobjectdef
2条回答

如果您使用的是python3.6,那么这种情况可以利用新的__init_subclass__方法。当子类被创建时,它被子类调用。在

如果没有Python3.6,您必须使用元类。在

decorator本身可以用所需的数据标记每个方法。在

def on_initialize(precedence=0):
    def marker(func):
        func._initializer = precedence
        return func
    return marker

def on_event(precedence=0):
    def marker(func):
        func._event_handler = precedence
        return func
    return marker


def on_finalize(precedence=0):
    def marker(func):
        func._finalizer = precedence
        return func
    return marker



class Framework:

    def __init_subclass__(cls, *args, **kw):
        super().__init_subclass__(*args, **kw)
        handlers = dict(_initializer=[], _event_handler=[], _finalizer=[])
        for name, method in cls.__dict__.items():
            for handler_type in handlers:
                if hasattr(method, handler_type):
                    handlers[handler_type].append((getattr(method, handler_type), name))

        for handler_type in handlers:
            setattr(cls, handler_type, 
                    [handler[1] for handler in sorted(handlers[handler_type])])

    def initialize(self):
        for method_name in self._initializer:
            getattr(self, method_name)()

    def handle_event(self, event):
        for method_name in self._event_handler:
            getattr(self, method_name)(event)

    def finalize(self):
        for method_name in self._finalizer:
            getattr(self, method_name)()

    def run(self):
        self.initialize()

        for event in range(10):
            self.handle_event(event)

        self.finalize()

如果您有一个复杂的类层次结构,应该正确地继承操作方法,那么在将其作为类属性应用之前,您必须将handlers字典中的列表与超类中的列表合并(将超类作为cls.__mro__[1])应用。在

另外,如果使用的是Python<;3.6,则需要将__init_subclass__上的逻辑移到元类中。只需将代码放在元类的__init__方法上(并适当地调整传入参数和超级调用),它的工作原理应该是一样的。在

我的想法是使用基于类的decorator,它很简单,并且提供中间上下文以便在修饰函数之间共享。所以decorator应该是这样的(我使用的是python3.5):

class OnInitialize:
  methods = {}

  def __init__(self, precedence):
    self.precedence = precedence

  def __call__(self, func):
    self.methods[self.precedence] = func
    def wrapper(*a, **kw):
      for precedence in sorted(self.methods.keys()):
        self.methods[precedence](*a, **kw)
    return wrapper

在装饰时,首先执行init,并存储优先值以备将来使用。其次,执行调用,只将目标函数附加到方法字典中(请注意,调用方法结构可以定制为允许调用具有相同优先级的多个方法)。在

另一方面,目标类和方法应该是这样的

^{pr2}$

这确保了,如果调用以下方法之一,它将以给定的顺序调用所有修饰的方法。在

target = Target()
target.initialize()

希望有帮助,如果你对其他东西感兴趣,请在下面评论我。在

相关问题 更多 >

    热门问题