【问题标题】:Using iter on an existing iterator in Python: What happens to the iterator?在 Python 中的现有迭代器上使用 iter:迭代器会发生什么?
【发布时间】:2015-02-26 14:30:06
【问题描述】:

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

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

返回 1。

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

【问题讨论】:

  • 任何 next() 都会影响所有其他人

标签: python iterator


【解决方案1】:

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 */
    ....

但这对于用户空间对象来说不是必须的:

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

【讨论】:

  • 并不像我想象的那么简单。我想我必须移动已回答的标记。 :-)
【解决方案2】:

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

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

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

【讨论】:

    猜你喜欢
    • 2014-05-24
    • 2020-06-29
    • 2014-06-13
    • 2019-04-12
    • 2021-01-20
    • 2018-05-16
    • 2011-05-16
    • 1970-01-01
    • 2010-11-06
    相关资源
    最近更新 更多