这是我的情况:

我有这样的课:

class Handler:
    def __init__(self, name):
        self.name = name

    def gogo(self, input):
        print("My name is %s and I got %s" % (self.name, input))


我想要实现的是这样的:

dispatcher = Dispatcher(Handler("who"), Handler("what"))
dispatcher.gogo("food")

>> "My name is who and I got food"
>> "My name is what and I got food"


我的第一个尝试是创建一个Dispatcher类,该类在其__init__方法中创建自己的方法。在这种情况下,Dispatcher的每个方法只会在不同的处理程序上触发相同的方法。缺点是,初始化分派器后,如果将任何新方法添加到处理程序中,将无法使用。

因此,我的第二个尝试是让__getattr__方法生成一个新方法,每次调用该方法时都会调用处理程序方法,因此基本上是这样的:

def __getattr__(self, item):
    methods = []
    for destination in self._destinations:
        if hasattr(destination, item):
            destination_method = getattr(destination, item)

            # if the argument is not callable, we are not interested, we cannot do anything with it
            # Maybe we should even raise an error here?
            if callable(destination_method):
                methods.append(destination_method)

    # If none of the destinations had a method for this name, we cannot do anything and should raise
    if len(methods) == 0:
        raise NotImplementedError("No method found for property %s" % item)

    # Create a wrapper around the methods that we detected that will just pass the arguments
    def new_method(*args, **kwargs):
        for method in methods:
            method(*args, **kwargs)

    return new_method


该方法的缺点是每次都会生成一个新方法,通常这并不是超级好。另外,它只是感觉不太好,并且容易出错(例如,调度程序非常不透明,当您获得调度程序时,您将无法确定是否有可用的方法)。

我要实现的方法数量是已知的,因此从理论上讲,我可以为所有处理程序提供一个基类,该处理程序将包含它们可能实现的每个方法。

我正在寻找一种尽可能优雅的解决方案,因为它应该是一个非常简单的系统,所以不会在dispatcher.gogo("food")中涉及大量开销。

最佳答案

为什么不将调度程序方法从本地范围移到实例级别?

class Dispatcher():

    def __dispatch(self, *args , **kwargs):
        for method in self.__methods:
            method(*args, **kwargs)

    def __getattr__(self, item):
        self.__methods = []
        …
                if callable(destination_method):
                    self.__methods.append(destination_method)
        …
        return self.__dispatch

07-25 21:40
查看更多