有没有像这样的方法?到目前为止,我找到的唯一解决方案是致电isiterable
hasattr(myObj, '__iter__')
但我不确定这有多万无一失。
网友回答:
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)
__iter__()
__getitem__()
iter(obj)
网友回答:
__iter__
try:
some_object_iterator = iter(some_object)
except TypeError as te:
print(some_object, 'is not iterable')
内置检查方法,如果是字符串,则检查方法。iter
__iter__
__getitem__
一种 pythonic 编程风格,通过检查对象的方法或属性签名来确定对象的类型,而不是通过与某个类型对象的显式关系来确定对象(“如果它看起来像鸭子,嘎嘎叫像鸭子,它一定是鸭子。通过强调接口而不是特定类型,设计良好的代码通过允许多态替换来提高其灵活性。鸭子类型避免使用 type() 或 isinstance() 进行测试。相反,它通常采用EAFP(比许可更容易请求宽恕)风格的编程。
…
try: _ = (e for e in my_object) except TypeError: print my_object, 'is not iterable'
collections
from collections.abc import Iterable
if isinstance(e, Iterable):
# e is iterable
但是,这不会检查可通过 迭代的类。__getitem__
网友回答:
我想更多地阐明 的相互作用,以及幕后发生的事情。有了这些知识,您将能够理解为什么您能做的最好的事情是iter
__iter__
__getitem__
try:
iter(maybe_iterable)
print('iteration will probably work')
except TypeError:
print('not iterable')
我将首先列出事实,然后快速提醒您在python中使用循环时会发生什么,然后进行讨论以说明事实。for
o
iter(o)
a) 有一个返回迭代器对象的方法。迭代器是具有 and a (Python 2: ) 方法的任何对象。o
__iter__
__iter__
__next__
next
b)有一个方法。o
__getitem__
Iterable
Sequence
__iter__
o
__getitem__
__iter__
iter(o)
o
IndexError
StopIteration
iter
o
__iter__
iter
__iter__
__getitem__
__iter__
赢了。如果对象同时实现 和 ,将调用 。o
__iter__
__getitem__
iter(o)
__iter__
__iter__
for
循环为了跟上进度,你需要了解在Python中使用循环时会发生什么。如果您已经知道,请随时直接跳到下一部分。for
当你使用一些可迭代的对象时,Python调用并期望一个迭代器对象作为返回值。迭代器是实现(或在 Python 2 中)方法和方法的任何对象。for item in o
o
iter(o)
__next__
next
__iter__
按照惯例,迭代器的方法应该返回对象本身(即 )。然后 Python 调用迭代器,直到被引发。所有这些都隐式发生,但以下演示使其可见:__iter__
return self
next
StopIteration
import random
class DemoIterable(object):
def __iter__(self):
print('__iter__ called')
return DemoIterator()
class DemoIterator(object):
def __iter__(self):
return self
def __next__(self):
print('__next__ called')
r = random.randint(1, 10)
if r == 5:
print('raising StopIteration')
raise StopIteration
return r
迭代 :DemoIterable
>>> di = DemoIterable()
>>> for x in di:
... print(x)
...
__iter__ called
__next__ called
9
__next__ called
8
__next__ called
10
__next__ called
3
__next__ called
10
__next__ called
raising StopIteration
关于第 1 点和第 2 点:获取迭代器和不可靠的检查
请考虑以下类:
class BasicIterable(object):
def __getitem__(self, item):
if item == 3:
raise IndexError
return item
使用 的实例调用将返回一个迭代器,没有任何问题,因为实现 .iter
BasicIterable
BasicIterable
__getitem__
>>> b = BasicIterable()
>>> iter(b)
<iterator object at 0x7f1ab216e320>
但是,重要的是要注意,它没有该属性,并且不被视为 或 的实例:b
__iter__
Iterable
Sequence
>>> from collections import Iterable, Sequence
>>> hasattr(b, '__iter__')
False
>>> isinstance(b, Iterable)
False
>>> isinstance(b, Sequence)
False
这就是为什么Luciano Ramalho的Fluent Python建议调用和处理潜力作为检查对象是否可迭代的最准确方法。直接引用书中的话:iter
TypeError
从 Python 3.4 开始,检查对象是否可迭代的最准确方法是调用并处理异常(如果不是)。这比使用 更准确,因为也会考虑传统方法,而 ABC 则不考虑。
x
iter(x)
TypeError
isinstance(x, abc.Iterable)
iter(x)
__getitem__
Iterable
在第 3 点:迭代仅提供__getitem__
但不提供__iter__
的对象
遍历 的实例按预期工作:Python
构造一个迭代器,该迭代器尝试按索引获取项目,从零开始,直到引发 an。演示对象的方法仅返回由 返回的迭代器作为参数提供的 。BasicIterable
IndexError
__getitem__
item
__getitem__(self, item)
iter
>>> b = BasicIterable()
>>> it = iter(b)
>>> next(it)
0
>>> next(it)
1
>>> next(it)
2
>>> next(it)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
请注意,迭代器在无法返回下一项时引发,并且引发的 for 在内部处理。这就是为什么循环使用 a 按预期工作的原因:StopIteration
IndexError
item == 3
BasicIterable
for
>>> for x in b:
... print(x)
...
0
1
2
下面是另一个示例,以便说明迭代器如何尝试按索引访问项目的概念。 不继承自 ,这意味着实例没有方法。iter
WrappedDict
dict
__iter__
class WrappedDict(object): # note: no inheritance from dict!
def __init__(self, dic):
self._dict = dic
def __getitem__(self, item):
try:
return self._dict[item] # delegate to dict.__getitem__
except KeyError:
raise IndexError
请注意,调用 to 是委托给的,方括号表示法只是一种简写。__getitem__
dict.__getitem__
>>> w = WrappedDict({-1: 'not printed',
... 0: 'hi', 1: 'StackOverflow', 2: '!',
... 4: 'not printed',
... 'x': 'not printed'})
>>> for x in w:
... print(x)
...
hi
StackOverflow
!
在第 4 点和第 5 点:iter
在调用迭代器时检查迭代器__iter__
:
当为对象调用 时,将确保 的返回值 ,如果该方法存在,则是一个迭代器。这意味着返回的对象
必须实现(或在 Python 2 中)和 . 不能对仅
提供 的对象执行任何健全性检查,因为它无法检查对象的项目是否可通过整数索引访问。iter(o)
o
iter
__iter__
__next__
next
__iter__
iter
__getitem__
class FailIterIterable(object):
def __iter__(self):
return object() # not an iterator
class FailGetitemIterable(object):
def __getitem__(self, item):
raise Exception
请注意,从实例构造迭代器会立即失败,而从实例构造迭代器会成功,但在第一次调用 时会引发异常。FailIterIterable
FailGetItemIterable
__next__
>>> fii = FailIterIterable()
>>> iter(fii)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: iter() returned non-iterator of type 'object'
>>>
>>> fgi = FailGetitemIterable()
>>> it = iter(fgi)
>>> next(it)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/path/iterdemo.py", line 42, in __getitem__
raise Exception
Exception
第6点:__iter__
获胜
这个很简单。如果对象实现 和 ,将调用 。考虑以下类__iter__
__getitem__
iter
__iter__
class IterWinsDemo(object):
def __iter__(self):
return iter(['__iter__', 'wins'])
def __getitem__(self, item):
return ['__getitem__', 'wins'][item]
以及循环遍历实例时的输出:
>>> iwd = IterWinsDemo()
>>> for x in iwd:
... print(x)
...
__iter__
wins
关于第 7 点:您的可迭代类应该实现__iter__
您可能会问自己,为什么大多数内置序列(如实现方法)就足够了。list
__iter__
__getitem__
class WrappedList(object): # note: no inheritance from list!
def __init__(self, lst):
self._list = lst
def __getitem__(self, item):
return self._list[item]
毕竟,迭代上述类的实例(委托调用到(使用方括号表示法)将正常工作:__getitem__
list.__getitem__
>>> wl = WrappedList(['A', 'B', 'C'])
>>> for x in wl:
... print(x)
...
A
B
C
自定义可迭代对象应实现的原因如下:__iter__
__iter__
isinstance(o, collections.abc.Iterable)
True
__iter__
iter
TypeError
__getitem__
这就是为什么任何 Python 序列都是可迭代的:它们都实现了 .事实上,标准序列也实现了 ,你的也应该实现,
因为
出于向后兼容性的原因存在的特殊处理,并且将来可能会
消失(尽管在我写这篇文章时它没有被弃用)。__getitem__
__iter__
__getitem__
模板简介:该模板名称为【Python类型检查方法】,大小是暂无信息,文档格式为.编程语言,推荐使用Sublime/Dreamweaver/HBuilder打开,作品中的图片,文字等数据均可修改,图片请在作品中选中图片替换即可,文字修改直接点击文字修改即可,您也可以新增或修改作品中的内容,该模板来自用户分享,如有侵权行为请联系网站客服处理。欢迎来懒人模板【Python】栏目查找您需要的精美模板。