【发布时间】:2014-08-07 02:41:41
【问题描述】:
我正在创建类 Foo 的实例,并且我希望能够以通用方式从各种类型中实例化这些实例。您不能将 Foo 传递给字典或列表。请注意,Foo 来自第 3 方代码库 - 我无法更改 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 块似乎到达了同一个地方,但不那么直接。其次,如果错误没有像这样清晰地映射怎么办? (例如,如果传递 list 或 dict 会引发 TypeError)
编辑:我不是 try/except 方法的忠实粉丝的第三个原因是我需要去查找 Foo 在这些情况下会抛出哪些异常,而不是能够预先对其进行编码。
【问题讨论】:
-
一般来说,我认为这是三个完全独立的函数。它们都返回没有通用接口的不同类型,所以我看不到一个地方你不会先验地知道你将要从中构造
Foo的类型,因为你需要知道如何处理返回Foo、list(Foo)或dict((str, Foo))。 -
另外请记住,python 中的任何类型检查都不沿继承链查看,仅查看直接实例类型。这意味着您的类型检查对于 行为类似于
lists(例如,一个集合或任何真正的可迭代对象)或 行为类似dicts的事物将始终失败,例如OrderedDict或defaultdict。singledispatch稍微好一点,因为它会沿着继承链寻找一个共同的祖先,但仍然无法通过 acts-like 测试。 -
我同意可以事先知道传递的对象是列表还是字典,并进行适当处理。我希望的是一个能够优雅地处理我感兴趣的大多数情况的函数,即单个实例、列表、字典、列表列表等。看起来 try/except 块可以做到这一点,但是不能保证对于您可能有兴趣支持的每种类型的例外都是唯一的。
标签: python types typechecking