有没有像isiterable这样的方法?到目前为止,我找到的唯一解决办法就是打电话
hasattr(myObj, '__iter__')
但我不确定这是否万无一失。
有没有像isiterable这样的方法?到目前为止,我找到的唯一解决办法就是打电话
hasattr(myObj, '__iter__')
但我不确定这是否万无一失。
当前回答
根据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__方法。
其他回答
在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基础结构非常有用。
你可以试试这个:
def iterable(a):
try:
(x for x in a)
return True
except TypeError:
return False
如果我们可以创建一个迭代它的生成器(但从不使用生成器,以免占用空间),那么它就是可迭代的。听起来像是"废话"一类的事。为什么首先需要确定一个变量是否可迭代?
如果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
这是不够的:__iter__返回的对象必须实现迭代协议(即next方法)。请参阅文档中的相关部分。
在Python中,一个好的实践是“尝试并查看”而不是“检查”。
不是真的“正确”,但可以作为最常见的类型,如字符串,元组,浮动等快速检查…
>>> '__iter__' in dir('sds')
True
>>> '__iter__' in dir(56)
False
>>> '__iter__' in dir([5,6,9,8])
True
>>> '__iter__' in dir({'jh':'ff'})
True
>>> '__iter__' in dir({'jh'})
True
>>> '__iter__' in dir(56.9865)
False