我想公开一个具有多态参数列表接口的方法:
def my_method(*args: Union[str, Type[MyType], Dict[str, Dict[str, str]] ):
pass
上下文是,我想允许一种方法来注册MyType
和初始化器参数。MyType的name属性是字符串。(这很有用,因为多个类可以映射到同一个名称,并且类的类别在运行时是可选的(。Dict[str, Dict[str, str]]
将此字符串名称映射到要传递给字符串的匹配类的参数。
因此客户端可以调用:
my_method("my_special_class"
FastMySpecialClass,
{"my_special_class": {"arg1": "foo", "arg2", "bar"}}
)
现在在my_method()
中,我唯一能想到的就是使用isinstance()
开关/机箱来处理这个问题。使用elseif
或处理程序函数的某种类型的dict。有点像这样:
for arg in args:
argument_resolver[type(arg)](arg)
我的直觉告诉我,这是一种处理多态性的糟糕方法,但我无法想出更好的方法。
对于不太复杂的场景,我建议使用functools.singledispatch
。然而,试图让这一点适用于varargs场景将是相当丑陋的。我能想到的最好的解决方案是在args
tuple
的每个元素上有一个由my_method
调用的单独函数,并用functools.singledispatch
实现该单独函数。
需要明确的是,在引擎盖下,functools.singledispatch
实际上只是在做一个稍微优化的isinstance
检查版本(它维护了dict
映射类型到实现函数;如果注册了精确的类型,则查找为O(1)
,但对于子类和ABC等,则必须回退到线性扫描(。但它通常看起来比将所有内容混合在一个函数中更干净,该函数实现了一大堆类型的行为。