简体   繁体   English

如何区分序列和映射

[英]How to distinguish between a sequence and a mapping

I would like to perform an operation on an argument based on the fact that it might be a map-like object or a sequence-like object. 我想基于它可能是类似地图的对象或类似序列的对象的事实对参数执行操作。 I understand that no strategy is going to be 100% reliable for type-like checking, but I'm looking for a robust solution. 我知道没有策略可以100%可靠地进行类型检查,但我正在寻找一个强大的解决方案。

Based on this answer , I know how to determine whether something is a sequence and I can do this check after checking if the object is a map. 基于这个答案 ,我知道如何确定某些东西是否是一个序列,我可以在检查对象是否是地图后进行检查。

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

Because a sequence can be seen as a map where keys are integers, should I just try to find a key that is not an integer? 因为序列可以看作键是整数的映射,我应该尝试找到一个不是整数的键吗? Or maybe I could look at the string representation? 或者我可以查看字符串表示? or...? 要么...?

UPDATE UPDATE

I selected SilentGhost's answer because it looks like the most "correct" one, but for my needs, here is the solution I ended up implementing: 我选择了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

Essentially, I don't want to rely on an ABC because there are many custom classes that behave like sequences and dictionary but that still do not extend the python collections ABCs (see @Manoj comment). 本质上,我不想依赖ABC,因为有许多自定义类的行为类似于序列和字典,但仍然没有扩展python集合ABCs(参见@Manoj评论)。 I thought the keys attribute (mentioned by someone who removed his/her answer) was a good enough check for mappings. 我认为密钥属性(由删除他/她的答案的人提到)是对映射的足够好的检查。

Classes extending the Sequence and Mapping ABCs will work with this solution as well. 扩展序列和映射ABC的类也将与此解决方案一起使用。

>>> 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) collections抽象基类(ABCs)

Sequences have an __add__ method that implements the + operator. 序列有一个__add__方法实现+运算符。 Maps do not have that method, since adding to a map requires both a key and a value, and the + operator only has one right-hand side. 地图没有该方法,因为添加到地图需要键和值,而+运算符只有一个右侧。

So you may try: 所以你可以尝试:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM