Python hasattr(obj和iter)与集合

Python hasattr(obj和iter)与集合,python,collections,iterator,Python,Collections,Iterator,我看到一些帖子建议使用isinstance(obj,collections.Sequence)而不是hasattr(obj,'.''.'iter'.'来确定某个东西是否是一个列表 起初我很兴奋,因为测试一个对象是否有\uuuu iter\uuuu对我来说总是很肮脏。但在进一步审查之后,这似乎仍然是最好的解决方案,因为对集合进行的isinstance测试都不会产生相同的结果collections.Sequence已关闭,但它返回字符串的True hasattr(obj, '__iter__')

我看到一些帖子建议使用
isinstance(obj,collections.Sequence)
而不是
hasattr(obj,'.''.'iter'.'
来确定某个东西是否是一个列表

起初我很兴奋,因为测试一个对象是否有
\uuuu iter\uuuu
对我来说总是很肮脏。但在进一步审查之后,这似乎仍然是最好的解决方案,因为对
集合进行的
isinstance
测试都不会产生相同的结果
collections.Sequence
已关闭,但它返回字符串的
True

hasattr(obj, '__iter__')
    set([]): True
    {}: True
    []: True
    'str': False
    1: False

isinstance(obj, collections.Iterable)
    set([]): True
    {}: True
    []: True
    'str': True
    1: False

isinstance(obj, collections.Iterator)
    set([]): False
    {}: False
    []: False
    'str': False
    1: False

isinstance(obj, collections.Sequence)
    set([]): False
    {}: False
    []: True
    'str': True
    1: False
以下是我用来生成此代码的代码:

import collections

testObjs = [
    set(),
    dict(),
    list(),
    'str',
    1
]

print "hasattr(obj, '__iter__')"
for obj in testObjs:
    print '    %r: %r' % (obj, hasattr(obj, '__iter__'))
print

print "isinstance(obj, collections.Iterable)"
for obj in testObjs:
    print '    %r: %r' % (obj, isinstance(obj, collections.Iterable))
print

print "isinstance(obj, collections.Iterator)"
for obj in testObjs:
    print '    %r: %r' % (obj, isinstance(obj, collections.Iterator))
print

print "isinstance(obj, collections.Sequence)"
for obj in testObjs:
    print '    %r: %r' % (obj, isinstance(obj, collections.Sequence))
print
我是否遗漏了一些东西,或者
hasattr(obj,'.'iter'.'uuu')
仍然是测试某些东西是否合适的最佳选择


编辑:我只对检测内置类型感兴趣:
dict
list
set
编辑:这很愚蠢:)

编辑:我应该包括让我研究这个问题的用例。我有一个函数,它接受一个arg,可以是一个值,也可以是一个序列。所以我想检测它是什么,如果它是一个单一的值,我想把它转换成一个序列,然后我可以把它作为一个序列来处理

if hasattr(arg, '__iter__'):
    arg= set(arg)
else:
    arg= set([arg])
解决这个问题的一个方法是,如果对象无法迭代,就让它抛出一个异常。但这在我的用例中不起作用。另一种解决方案是使用以下方法:

import collections

def issequenceforme(obj):
    if isinstance(obj, basestring):
        return False
    return isinstance(obj, collections.Sequence)
发件人:

但这需要定义这个函数,这使我不想使用它


看起来
hasattr(arg,'.'uu iter'.'uu')
仍然是最好的选择。

您也可以将
\uuu iter'.
添加到您自己的类中,因此任何缺少
hasattr(obj,'.'uu iter'.
的测试都不能保证检测到它们。您没有在问题中指定您只关心内置集合。

集合。
可伸缩性将保证对象是否可伸缩(如在obj
中为x使用
),但选中
则不会


字符串是一种可移植的数据类型,但在Python2.x上它没有
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

方法。

在与一些同事交谈后,我得出结论,hasattr(arg,“\uuuuuuuuuuuuuuuuuuuiter_uuuuuuuu')
可能是一个不错的单行程序,但正如你们所指出的那样,它。这就是我的结局:

if isinstance(arg, basestring):
    arg= set([arg])
else:
    try:
        selection= set(arg)
    except TypeError:
        selection= set([arg])
collections.Sequence
已关闭,但它为字符串返回True

hasattr(obj, '__iter__')
    set([]): True
    {}: True
    []: True
    'str': False
    1: False

isinstance(obj, collections.Iterable)
    set([]): True
    {}: True
    []: True
    'str': True
    1: False

isinstance(obj, collections.Iterator)
    set([]): False
    {}: False
    []: False
    'str': False
    1: False

isinstance(obj, collections.Sequence)
    set([]): False
    {}: False
    []: True
    'str': True
    1: False
  • collections.Iterable
    用于一个Iterable对象,即某种形式的容器,允许您逐个迭代它包含的对象。字符串包括在其中,因为您可以迭代每个字符都是字符串
  • collections.Sequence
    用于保证迭代顺序的iterable对象子集。列表和字符串将返回
    True
    ,因为同一列表或字符串的迭代顺序始终相同,而集合和字典将返回
    False
    ,因为您不知道内部对象的顺序
如果您确定只想检测内置类型(通常被认为是可疑行为,首选),那么您可以这样做:

if isinstance(arg, (set, list, dict, tuple)):
    print "I got a built-in iterable."
else:
    print "Hey, this ain't iterable!"
然而,您提出的解决方案更好——处理任何特殊情况(例如,您的情况下的字符串),然后使用duck类型。这样,其他人就可以使用任何适合他们需要的容器,并负责确保它符合您的代码要求

问题:我看到一些帖子建议使用isinstance(obj,collections.Sequence)而不是hasattr(obj,'.''.'iter'.'来确定某个东西是否是一个列表

要确定某物是否是,最可靠的方法是尝试创建一个。这将确定对象是否实际可编辑:

def is_iterable(obj):
    try:
        iter(obj)
    except TypeError:
        return False
    else:
        return True
isinstance(obj, collections.Iterable)
一种稍微不太可靠,但外观整洁的方法是针对测试对象进行测试。这将测试对象是否具有_uiter _;()方法,或者是否注册为Iterable(例如,str的实例没有_uiter _;()方法,但注册为Iterable):

如果您对列表和类似列表的对象特别感兴趣,可以针对可变序列ABC进行测试:


也就是说,如果您依赖的对象具有特定的类似列表的行为,python的方法是假设该方法存在,如果不存在,则捕获异常。这被称为。

就个人而言,我检查
isinstance(obj,basestring)
(iterable,但通常不是你想要迭代的东西),如果不是,就迭代它,捕捉异常。我只对检测内置类型感兴趣,比如
dict
list
,和
set
。我将把这一点添加到我的问题中。检查
基本字符串
是常见且有用的。另一个有用的检查是
集合.Mapping
(而不是
dict
),特别是因为您似乎对集合感兴趣,
Mapping
的键始终是集合。