我正在创建类Foo的实例,并且我希望能够以各种类型的一般方式实例化这些实例。你不能通过Foo dict或list。请注意,Foo来自第三方代码库 - 我无法更改Foo的代码。
我知道Python中的类型检查函数参数被认为是错误的形式。是否有更多的Pythonic方法来编写下面的函数(即没有类型检查)?
def to_foo(arg):
if isinstance(arg, dict):
return dict([(key,to_foo(val)) for key,val in arg.items()])
elif isinstance(arg, list):
return [to_foo(i) for i in arg]
else:
return Foo(arg)
编辑:可以使用try / except块。例如,您可以这样做:
def to_foo(arg):
try:
return Foo(arg)
except ItWasADictError:
return dict([(key,to_foo(val)) for key,val in arg.items()])
except ItWasAListError:
return [to_foo(i) for i in arg]
我对此并不完全满意有两个原因:首先,类型检查似乎更直接地解决了所需的功能,而这里的try / except块看起来好像是到了同一个地方但不那么直接。第二,如果错误没有像这样干净地映射怎么办? (例如,如果传递列表或dict会抛出TypeError)
编辑:第三个原因我不是这里的try / except方法的忠实粉丝我需要去查找Foo在这些情况下会抛出的异常,而不是能够对其进行编码前面。
答案 0 :(得分:4)
如果您使用的是python 3.4,则可以使用functools.singledispatch或a backport for a different python version
from functools import singledispatch
@singledispatch
def to_foo(arg):
return Foo(arg)
@to_foo.register(list)
def to_foo_list(arg):
return [Foo(i) for i in arg]
@to_foo.register(dict)
def to_foo_dict(arg):
return {key: Foo(val) for key, val in arg.items()}
这是python的一个相当新的构造,但是在其他语言中是一种常见的模式。我不确定你是否会称之为pythonic,但它确实感觉比在任何地方写isinstances
更好。虽然在实践中,singledispatch可能只是在内部为您进行实例检查。
答案 1 :(得分:2)
处理问题的pythonic方法是继续(首先)假设arg
为Foo
并且除了任何错误:
try:
x = Foo(arg)
except NameError:
#do other things
这个想法的短语是"duck typing",它在python中是一种流行的模式。