hasattr(obj,'__ user__')vs collections

kee*_*n3d 12 python collections iterator

我已经看到一些帖子推荐isinstance(obj, collections.Sequence)而不是hasattr(obj, '__iter__')确定某些内容是否是列表.

len(object)或hasattr(object,__iter__)?

Python:检查对象是否是序列

起初我很兴奋,因为测试一个物体__iter__对我来说总是很脏.但经过进一步审查后,这似乎仍然是最好的解决方案,因为没有一个isinstance测试collection产生相同的结果.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
Run Code Online (Sandbox Code Playgroud)

这是我用来生成这个的代码:

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
Run Code Online (Sandbox Code Playgroud)

我是否遗漏了某些东西,或者hasattr(obj, '__iter__')仍然是测试某些东西是否可迭代的最佳选择?

编辑:我只是在检测内建类型感兴趣的是:dict,list,和set.(编辑:这是愚蠢的:))

编辑:我应该包括让我调查此用途的用例.我有一个函数,它接受一个可以是单个值或序列的arg.所以我想检测它是什么,如果它是单个值就把它变成一个序列,所以我可以把它作为一个序列来处理.

if hasattr(arg, '__iter__'):
    arg= set(arg)
else:
    arg= set([arg])
Run Code Online (Sandbox Code Playgroud)

对此的一个解决方案是,如果无法迭代对象,则抛出异常.但这在我的用例中不起作用.另一个解决方案是使用类似的东西:

import collections

def issequenceforme(obj):
    if isinstance(obj, basestring):
        return False
    return isinstance(obj, collections.Sequence)
Run Code Online (Sandbox Code Playgroud)

来自: Python:检查对象是否是序列

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

它看起来hasattr(arg, '__iter__')仍然是最好的选择.

JBe*_*rdo 5

collections.Iterable会保证对象是可迭代或不(像使用for x in obj),但检查__iter__不会.

字符串是可迭代的数据类型,但在Python2.x上它没有__iter__方法.


kee*_*n3d 1

在与一些同事交谈后,我得出的结论是,这hasattr(arg, '__iter__')可能是一个不错的衬里,但它远非完美,正如你们也指出的那样。这就是我最终得到的结果:

if isinstance(arg, basestring):
    arg= set([arg])
else:
    try:
        selection= set(arg)
    except TypeError:
        selection= set([arg])
Run Code Online (Sandbox Code Playgroud)