Jas*_*n S 5 python polymorphism types python-2.7
我想要一个函数,它通常接受X类型的参数,其中X是标量,列表或dict,并根据其他信息返回具有相同键值的X列表.
def foo(info, k):
return [bar(item,k) for item in processInfo(info)]
def bar(item, keydata):
# pseudocode follows.
# What we want to do is return an output of parallel type to the input key k,
# using the key data to lookup information from the input item.
if keydata is a scalar:
return item[keydata]
elif keydata is a list:
return [item[k] for k in keydata]
elif keydata is a dict:
return dict((k,item[v]) for (k,v) in keydata.iteritems())
else:
raise ValueError('bar expects a scalar, list, or dict')
Run Code Online (Sandbox Code Playgroud)
我的问题是,我如何在三种类型之间进行调度?
编辑:字符串将被解释为标量,而不是列表/可迭代.元组将被解释为可迭代的.
编辑2:我想要鸭子打字,而不是严格打字.
你需要做的事情以正确的顺序,因为str
和dict
类型是可迭代.
from collections import Iterable, Mapping # in Python 3 use from collections.abc
def bar(item, keydata):
if isinstance(keydata, Mapping):
return {k: item[v] for (k,v) in keydata.iteritems()}
elif isinstance(keydata, Iterable) and not isinstance(keydata, str):
return [item[k] for k in keydata]
return item[keydata]
Run Code Online (Sandbox Code Playgroud)
这取决于您对输入的严格程度。该isinstance
方法强制您指定要接受的类型(即,没有鸭子类型)。只要您的用户仅传递这些类或这些类的子类型,它就可以工作。您还可以尝试通过参数支持的方法来区分参数。一个例子是
编辑:添加了字符串的特殊情况
if isinstance(keydata, basestring):
# special case to avoid considering strings as containers
# for python 3.x use str instead of basestring
return item[keydata]
try:
return dict((k,item[v]) for (k,v) in keydata.iteritems())
except AttributeError:
# it's not a dict-like
pass
try:
return [item[k] for k in keydata]
except TypeError:
# it's not iterable
return item[keydata]
Run Code Online (Sandbox Code Playgroud)
控制流的选择取决于您想要的灵活性,以及您希望如何处理不明确的情况。例如,字符串被视为字符序列还是标量?