如何区分序列和映射

时间:2010-10-04 10:45:43

标签: python dictionary sequence

我想基于它可能是类似地图的对象或类似序列的对象的事实对参数执行操作。我知道没有任何策略可以100%可靠地进行类型检查,但我正在寻找一个强大的解决方案。

基于这个answer,我知道如何判断某些东西是否是序列,我可以在检查对象是否是地图后进行检查。

def ismap(arg):
   # How to implement this?

def isseq(arg):
   return hasattr(arg,"__iter__")

def operation(arg):
   if ismap(arg):
      # Do something with a dict-like object
   elif isseq(arg):
      # Do something with a sequence-like object
   else:
      # Do something else

因为序列可以看作键是整数的映射,我应该尝试找到一个不是整数的键吗?或者我可以查看字符串表示?或...?

更新

我选择了SilentGhost的答案,因为它看起来是最“正确”的答案,但根据我的需要,这是我最终实施的解决方案:

if hasattr(arg, 'keys') and hasattr(arg, '__getitem__'):
   # Do something with a map
elif hasattr(arg, '__iter__'):
   # Do something with a sequence/iterable
else:
   # Do something else

基本上,我不想依赖ABC,因为有许多自定义类的行为类似于序列和字典,但仍然没有扩展python集合ABCs(参见@Manoj评论)。我认为密钥属性(由删除他/她的答案的人提到)是对映射的足够好的检查。

扩展序列和映射ABC的类也适用于此解决方案。

2 个答案:

答案 0 :(得分:10)

>>> from collections import Mapping, Sequence
>>> isinstance('ac', Sequence)
True
>>> isinstance('ac', Mapping)
False
>>> isinstance({3:42}, Mapping)
True
>>> isinstance({3:42}, Sequence)
False

collections abstract base classes (ABCs)

答案 1 :(得分:1)

序列有__add__方法实现+运算符。地图没有这种方法,因为添加到地图需要键和值,而+运算符只有一个右侧。

所以你可以试试:

def ismap(arg):
    return isseq(arg) and not hasattr(arg, "__add__")