在Python中的现有迭代器上使用iter:迭代器会发生什么?

时间:2015-02-26 14:30:06

标签: python iterator

iter function包装列表或元组之类的对象,以便将它们用作迭代器,例如,可以使用next。例如,

next(iter([1, 2, 3]))

返回1.

如果我们传递给iter的对象已经是迭代器,那么内部会发生什么?它只是返回原始对象,即无操作?或者它是否会生成一个包装原始迭代器的新迭代器?通过包装我当然不是指复制原始迭代器。

2 个答案:

答案 0 :(得分:3)

TLDNR:iter返回obj.__iter_。它不会返回obj""。

iter的Cpython实现非常简单:

PyObject *
PyObject_GetIter(PyObject *o)
{
    PyTypeObject *t = o->ob_type;
    getiterfunc f = NULL;
    if (PyType_HasFeature(t, Py_TPFLAGS_HAVE_ITER))
        f = t->tp_iter; // <- if it has __iter__, return that
    ....more stuff

因此,当您致电iter(obj)并且obj.__iter__存在时,它就会返回。大多数(所有?)内置迭代器都有__iter__ = self,例如

PyTypeObject PyListIter_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "listiterator",                             /* tp_name */
    ....
    PyObject_SelfIter,                          /* tp_iter */
    ....

但对于userland对象来说,这不是必需的:

class X:
    def __iter__(self):
        return Y()

class Y:
    def __iter__(self):
        return iter('xyz')


a = iter(X())
b = iter(a)
print a is b # False

答案 1 :(得分:1)

经验证据很好,但是the docs are pretty explicit

  

迭代器必须有一个__iter__()方法,它返回迭代器对象本身

如果使用__next__()实现对象,则应该使用__iter__()方法返回self。打破这个规则意味着你有一个不是迭代器的对象,但看起来像是一个灾难的接收者。