这个问题的最一般的解决方案是使用与抽象基类集合的区别.
import collections
def get_iterable(x):
if isinstance(x, collections.Iterable):
return x
else:
return (x,)
您也可能想要测试basestring,如Kindall所示.
if isinstance(x, collections.Iterable) and not isinstance(x, basestring):
现在有些人可能会像以前一样想过,“不是真的吗considered harmful?它不会锁定你使用一种类型吗?不会使用hasattr(x,’__iter__’)更好?
答案是:不是当涉及抽象基类时.实际上,您可以使用__iter__方法定义自己的类,并将其识别为集合的实例.即使不对子集进行子集也是可以实现的.这是因为collections.Iterable定义了一个__subclasshook__,它确定传递给它的类型是否是通过它实现的任何定义的Iterable.
>>> class MyIter(object):
... def __iter__(self):
... return iter(range(10))
...
>>> i = MyIter()
>>> isinstance(i, collections.Iterable)
True
>>> collections.Iterable.__subclasshook__(type(i))
True