有没有像isiterable这样的方法?到目前为止,我找到的唯一解决办法就是打电话
hasattr(myObj, '__iter__')
但我不确定这是否万无一失。
有没有像isiterable这样的方法?到目前为止,我找到的唯一解决办法就是打电话
hasattr(myObj, '__iter__')
但我不确定这是否万无一失。
当前回答
Duck typing
try:
iterator = iter(the_element)
except TypeError:
# not iterable
else:
# iterable
# for obj in iterator:
# pass
类型检查
使用抽象基类。它们至少需要Python 2.6,并且只适用于新样式的类。
from collections.abc import Iterable # import directly from collections for Python < 3.3
if isinstance(the_element, Iterable):
# iterable
else:
# not iterable
然而,iter()更可靠一些,如文档所述:
检查isinstance(obj, Iterable)检测类 注册为Iterable或具有__iter__()方法,但是 它不会检测使用__getitem__()迭代的类 方法。唯一可靠的方法来确定一个对象是否 Is iterable调用iter(obj)。
其他回答
根据Python 2术语表,可迭代对象是
所有序列类型(如list、str和tuple)和一些非序列类型(如dict和file)以及使用__iter__()或__getitem__()方法定义的任何类的对象。可迭代对象可用于for循环和许多其他需要序列的地方(zip(), map(),…)。当一个可迭代对象作为参数传递给内置函数iter()时,它将返回该对象的迭代器。
当然,考虑到Python的一般编码风格,基于“请求原谅比请求许可更容易”这一事实。,一般的期望是使用
try:
for i in object_in_question:
do_something
except TypeError:
do_something_for_non_iterable
但如果你需要显式检查它,你可以通过hasattr(object_in_question, "__iter__")或hasattr(object_in_question, "__getitem__")来测试可迭代对象。你需要检查两者,因为strs没有__iter__方法(至少在Python 2中没有,在Python 3中有),而且生成器对象没有__getitem__方法。
如果object是可迭代的,下面代码中的isiterable函数将返回True。如果不是iterable则返回False
def isiterable(object_):
return hasattr(type(object_), "__iter__")
例子
fruits = ("apple", "banana", "peach")
isiterable(fruits) # returns True
num = 345
isiterable(num) # returns False
isiterable(str) # returns False because str type is type class and it's not iterable.
hello = "hello dude !"
isiterable(hello) # returns True because as you know string objects are iterable
我在这里找到了一个很好的解决方案:
isiterable = lambda obj: isinstance(obj, basestring) \
or getattr(obj, '__iter__', False)
在Python <= 2.5中,你不能也不应该——iterable是一个“非正式的”接口。
但是从Python 2.6和3.0开始,你可以利用新的ABC(抽象基类)基础设施以及一些内置的ABC,这些ABC在collections模块中可用:
from collections import Iterable
class MyObject(object):
pass
mo = MyObject()
print isinstance(mo, Iterable)
Iterable.register(MyObject)
print isinstance(mo, Iterable)
print isinstance("abc", Iterable)
现在,这是否可取,或者是否有效,只是一个惯例的问题。正如你所看到的,你可以将一个不可迭代的对象注册为Iterable——它将在运行时引发一个异常。因此,isinstance获得了一个“新的”含义——它只是检查“声明的”类型兼容性,这在Python中是一个很好的方法。
另一方面,如果你的对象不能满足你所需要的接口,你会怎么做?举个例子:
from collections import Iterable
from traceback import print_exc
def check_and_raise(x):
if not isinstance(x, Iterable):
raise TypeError, "%s is not iterable" % x
else:
for i in x:
print i
def just_iter(x):
for i in x:
print i
class NotIterable(object):
pass
if __name__ == "__main__":
try:
check_and_raise(5)
except:
print_exc()
print
try:
just_iter(5)
except:
print_exc()
print
try:
Iterable.register(NotIterable)
ni = NotIterable()
check_and_raise(ni)
except:
print_exc()
print
如果对象不满足您的期望,则抛出TypeError,但如果已经注册了正确的ABC,则检查将毫无用处。相反,如果__iter__方法可用,Python将自动识别该类的object为Iterable。
如果你只是期望一个可迭代对象,遍历它,然后忘记它。另一方面,如果您需要根据输入类型执行不同的操作,那么您可能会发现ABC基础结构非常有用。
在我的脚本中,我经常发现定义一个可迭代函数很方便。 (现在合并了Alfe建议的简化):
import collections
def iterable(obj):
return isinstance(obj, collections.Iterable):
因此,您可以测试任何对象是否具有非常可读的可迭代形式
if iterable(obj):
# act on iterable
else:
# not iterable
就像你对可调用函数所做的那样
编辑:如果你安装了numpy,你可以简单地做: 简单地说是什么
def iterable(obj):
try: iter(obj)
except: return False
return True
如果没有numpy,可以简单地实现这段代码或上面的代码。