有没有像isiterable这样的方法?到目前为止,我找到的唯一解决办法就是打电话
hasattr(myObj, '__iter__')
但我不确定这是否万无一失。
有没有像isiterable这样的方法?到目前为止,我找到的唯一解决办法就是打电话
hasattr(myObj, '__iter__')
但我不确定这是否万无一失。
当前回答
Pandas有这样一个内置功能:
from pandas.util.testing import isiterable
其他回答
try:
#treat object as iterable
except TypeError, e:
#object is not actually iterable
不要检查你的鸭子是否真的是一只鸭子,看看它是否可迭代,就像它是可迭代的一样对待它,如果不是就抱怨。
Pandas有这样一个内置功能:
from pandas.util.testing import isiterable
这是不够的:__iter__返回的对象必须实现迭代协议(即next方法)。请参阅文档中的相关部分。
在Python中,一个好的实践是“尝试并查看”而不是“检查”。
在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基础结构非常有用。
根据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__方法。