Python:检查对象是否不是“数组类型”
我想找一种方法来测试一个对象是否不是“列表类型”,也就是说,不仅仅是这个对象不能被迭代(比如,你可以对字符串或者实现了iter的方法的简单对象使用iter),还要确保这个对象不属于列表家族。我把“列表家族”定义为列表(list)、元组(tuple)、集合(set)、不可变集合(frozenset)或者任何从这些类型继承的东西。不过,因为可能还有我没想到的情况,我希望找到一种比对所有这些类型使用isinstance
更通用的方法。
我想到了两种可能的方法,但这两种方法都感觉有点笨,因为它们都要测试每一种可能的列表类型,我在寻找一个更通用的解决方案。
第一种选择:
return not isinstance( value, (frozenset, list, set, tuple,) )
第二种选择:
return not hasattr(value, '__iter__')
测试__iter__
属性是否足够?有没有更好的方法来判断一个对象是否不是列表类型?
提前谢谢你。
编辑:
(引用自对@Rosh Oxymoron的解决方案的评论):
现在更仔细地考虑定义,我觉得更准确的说法是我需要找到所有不属于数组类型的东西,但它仍然可以是字符串或其他简单对象……
检查collections.Iterable
仍然会对实现了__iter__
方法的对象返回True。
2 个回答
其实没有一个明确的“家族”可以定义这个概念,所以自然也就没办法去检查它。最接近的就是一个可迭代的对象,但它不是字符串。你可以先检查这个对象是否可以被迭代,然后再明确地检查它是不是字符串:
if isinstance(ob, collections.Iterable) and not isinstance(ob, types.StringTypes):
print "An iterable container"
更好的做法是总是要求传入一个可迭代的对象。如果你需要传一个单独的字符串 S
,那就传 [S]
这个形式。这样做的好处是,你可以灵活地处理字符串,例如:
alphabet = set('abcdefgijklmopqrstuvwxyz')
如果你特别处理字符串的话,你会遇到以下问题:
- 会破坏用最自然的方式传递字符集合的能力。
- 会导致用户自定义的字符串类型和其他类似字符串的容器(比如
array.array
,它也可以表示一块数据,就像字符串一样)之间的不一致。
字符串可以用来表示一段文本,也可以表示一组字符,因此它在某种程度上也像列表。
其实“list-ish”这个词并不存在,也没有什么神奇的内置功能可以用来“检查某个值是不是某种我不知道的类型集合”。
你用的这个方法 not isinstance( value, (frozenset, list, set, tuple,) )
还不错——它很清晰,也很直接。