如何避免对Python函数的类型检查参数

时间:2014-08-07 02:41:41

标签: python types typechecking

我正在创建类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在这些情况下会抛出的异常,而不是能够对其进行编码前面。

2 个答案:

答案 0 :(得分:4)

如果您使用的是python 3.4,则可以使用functools.singledispatcha 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方法是继续(首先)假设argFoo并且除了任何错误:

try:
    x = Foo(arg)
except NameError:
    #do other things

这个想法的短语是"duck typing",它在python中是一种流行的模式。