这是我的情况:
我有这样的课:
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