【问题标题】:Why is the followiing iterator with yield not working?为什么以下带有产量的迭代器不起作用?
【发布时间】:2014-07-09 01:51:07
【问题描述】:

好的,所以我的实际代码有些复杂,但我用以下示例代码说明了我遇到的问题:

我有一个类,它有一个列表作为其实例变量之一。我希望该类是可迭代的,并在 for 循环中调用 next 时返回列表中的下一个元素。

所以我有如下:

class SimplaWannaBeIteratable(object):
    def __init__(self, list_to_iter, **kwargs)
        self._list = list_to_iter
        self._item = None
        #... other code to initialize
    def __iter__(self):
        return self
    def next(self):
        self._item= next(self._list)
        return self._item
    def current(self):
        #So that other uses cases have the access to the current member
        return self._current

但是,如果我执行以下操作:

 iter_item = SimplaWannaBeIteratable([1,2,3,4,5])
 for item in iter_item:
    return item

我明白了:


列表对象不是迭代器。

如果我将下一个更改如下:

def next(self):
    self._item= next(iter((self._list)))
    return self._item

我得到无限输出。

谁能告诉我我需要做什么才能完成我想做的任务以及为什么上面的代码不起作用? 根据我的理解,每次 next 被称为与列表关联的迭代器对象被调用,它的 next 是 return。那么为什么我的列表找不到它的迭代器呢?

【问题讨论】:

  • 如果列表项发生变化,您将不得不使用不同的方法来检查这些值。例如,维护您的迭代器当前所在的索引并访问列表中的第 index 个值并递增。这完全取决于您打算如何使用它。

标签: python iterator generator


【解决方案1】:

你需要一个迭代器来迭代一个列表。列表本身不是迭代器,因此您不能在其上调用 next()

class SimplaWannaBeIteratable(object):
    def __init__(self, list_to_iter, **kwargs):
        self._list = list_to_iter
        self._item = None
    def __iter__(self):
        self._iter = iter(self._list) # create/initialize the iterator
        return self
    def __next__(self): # using the Python 3.x name
        self._item = next(self._iter) # use the iterator
        return self._item
    # ...

【讨论】:

  • 感谢@Jeff Mercado。如果列表项发生更改,它是否仍然有效,即如果我在列表中添加更多项,当我稍后执行 for 时是否会迭代这些项
  • @sharth:是的,但是他没有指定版本,所以我假设是 Python 3.x。
  • @JeffMercado:这当然是公平的。
【解决方案2】:

您在self._list 上调用next,这是一个列表,而不是迭代器。 next 只会推进迭代器,它不会从可迭代对象中设置迭代器。

def __init__(self, ...):
    # ...
    self._iterator = iter(self._list)

def next(self):
    self._item = next(self._iterator)
    return self._item

关于您的编辑,您将获得无限递归,因为您每次都在新的迭代器上调用 next,而不是同一个迭代器。所以你正在失去迭代器的状态。再一次,看我上面的例子,它设置了一次迭代器。

【讨论】:

    【解决方案3】:

    您尝试实现的__next__ special method 用于控制在每个渐进步骤中对类似容器的类的迭代。如果您不需要此功能而只是想让您的类可迭代,请省略该方法并从__iter__ 返回iter(self._list)

    class SimplaWannaBeIteratable(object):
        def __init__(self, list_to_iter, **kwargs):
            self._list = list_to_iter
            self._item = None
    
        def __iter__(self):
            return iter(self._list)
    
        def current(self):
            return self._current
    

    演示:

    >>> iter_item = SimplaWannaBeIteratable([1,2,3,4,5])
    >>> for item in iter_item:
    ...     item
    ...
    1
    2
    3
    4
    5
    >>>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多