在Python中区分标量,列表和字典参数的最佳方法是什么?

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:我想要鸭子打字,而不是严格打字.

Mar*_*som 5

你需要做的事情以正确的顺序,因为strdict类型是可迭代.

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)


Fel*_*ipe 3

这取决于您对输入的严格程度。该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)

控制流的选择取决于您想要的灵活性,以及​​您希望如何处理不明确的情况。例如,字符串被视为字符序列还是标量?