How to avoid type checking arguments to Python function
我正在创建一个类foo的实例,我希望能够以一种通用的方式从各种类型实例化这些实例。你不能通过口述或列表。请注意,foo来自第三方代码库-我无法更改foo的代码。
我知道python中的类型检查函数参数被认为是不好的形式。有没有比写下面的函数更简单的方法(例如,不进行类型检查)?
1 2 3 4 5 6 7 | 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块。例如,您可以执行以下操作:
1 2 3 4 5 6 7 | 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,则会引发类型错误)
编辑:第三个我不太喜欢Try/Except方法的原因是我需要去找出foo在这些情况下会抛出什么异常,而不是预先编码它。
如果您使用的是python 3.4,那么您可以使用functools.singledispatch,或者为不同的python版本使用backport。
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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结构,但在其他语言中是一个常见的模式。我不确定你是否会称之为Python,但它确实比在任何地方写
处理你的问题的方法是假设(第一)
1 2 3 4 | try: x = Foo(arg) except NameError: #do other things |
这个想法的短语是"duck-typing",这是Python中的一个流行模式。