迭代器也是可迭代的吗?

Is an iterator also an iterable?

我发现:

>>> a={'x':42, 'y':3.14, 'z':7}
>>> b=a.__iter__()
>>> b.__dir__()
['__next__', ..., '__iter__', ...]
>>> b
<set_iterator object at 0x7efdd4e5afc0>

迭代器总是有 __iter__ 方法吗?

根据 迭代器也是可迭代的。如果迭代器总是有 __iter__ 方法是真的?

迭代器是可迭代的。是的,迭代器总是有一个 __iter__ 方法。

在迭代器上调用 iter,它会调用 __iter__ 挂钩,returns 相同的迭代器:

>>> it = iter([]) # return iterator from iterable
>>> it is iter(iter(it)) is it.__iter__().__iter__().__iter__()
True

method chaining的经典例子。

您一定也注意到了,自定义 类 的迭代器协议的大多数实现总是遵循:

def __iter__(self):
    return self

也就是说,如果迭代没有委托给另一个迭代器,例如 return iter(...)

迭代器 不实现 iterator protocol 是非常违反直觉的,你不觉得吗? __iter__协议的实现描述如下:

iterator.__iter__()

Return the iterator object itself. This is required to allow both containers and iterators to be used with the for and in statements.

[强调我的]

此行为预期与内置函数返回的迭代器对象一致:

>>> m = map(None, [])
>>> m
<map object at 0x...>
>>> m is m.__iter__().__iter__().__iter__()
True

P.S:我为多次打电话给dunders道歉;让它看起来像是正确的做法。 But it's not!

一个可迭代对象需要实现一个__iter__ method or a __getitem__ method:

An object can be iterated over with for if it implements __iter__() or __getitem__().

迭代器需要一个 __iter__ 方法(即 returns self)和一个 __next__ 方法(我不是 100% 确定 __next__).

迭代器总是有 __iter__ 方法是真的吗?

是的!

这也记录在 Data model:

object.__iter__(self)

This method is called when an iterator is required for a container. This method should return a new iterator object that can iterate over all the objects in the container. For mappings, it should iterate over the keys of the container.

Iterator objects also need to implement this method; they are required to return themselves. For more information on iterator objects, see Iterator Types.

(强调我的)

关于你的第二个问题:

迭代器也是可迭代对象吗?

是的,因为它有一个 __iter__ 方法。

补充说明

除了正式实现之外,只需检查是否可以调用 iter() 即可轻松检查某些内容是否可迭代:

def is_iterable(something):
    try:
        iter(something)
    except TypeError:
        return False
    else:
        return True

同样,可以通过检查 iter() 是否调用了某些东西 returns 本身来检查某物是否是迭代器:

def is_iterator(something):
    try:
        return iter(something) is something  # it needs to return itself to be an iterator
    except TypeError:
        return False

但不要在开发代码中使用它们,这些只是为了“可视化”。大多数情况下,你只是使用 for ... in ... 迭代某些东西,或者如果你需要一个迭代器,你使用 iterator = iter(...) 然后通过调用 next(iterator) 来处理迭代器,直到它抛出 StopIteration.

迭代器是可迭代的。

已记录并解释 here:

Iterators are required to have an __iter__() method that returns the iterator object itself so every iterator is also iterable

可迭代对象不一定是迭代器

根据定义,迭代器必须有一个 __next__ 方法。举一个简单的反例:

>>> ''.__next__
AttributeError: 'str' object has no attribute '__next__'

字符串对象是可迭代对象,但不是迭代器。

迭代器总是有 __iter__ 方法吗?

是的。所有的迭代器都有一个 __iter__ 方法,returns 本身。来自 docs

iterator.__iter__()

Return the iterator object itself. This is required to allow both containers and iterators to be used with the for and in statements.