【问题标题】:How do I check if an iterator is actually an iterator container?如何检查迭代器是否实际上是迭代器容器?
【发布时间】:2023-04-10 00:17:01
【问题描述】:

我在下面有一个迭代器容器的虚拟示例(真实的容器读取的文件太大而无法放入内存):

class DummyIterator:
    def __init__(self, max_value):
        self.max_value = max_value

    def __iter__(self):
        for i in range(self.max_value):
            yield i

def regular_dummy_iterator(max_value):
    for i in range(max_value):
        yield i

这允许我不止一次地迭代值,这样我就可以实现这样的事情:

def normalise(data):
    total = sum(i for i in data)
    for val in data:
        yield val / total

# this works when I call next()
normalise(DummyIterator(100))

# this doesn't work when I call next()
normalise(regular_dummy_iterator(100))

如何检查规范化函数,我正在传递一个迭代器容器而不是一个普通的生成器?

【问题讨论】:

  • 您不必一次将文件读入内存,为什么需要这个?
  • 帕德莱克所说的。如果您需要对一个大文件执行多次传递,只需使用其.seek() 方法来回退它。
  • 您可以编辑您的代码以使其可运行吗?将self 参数添加到__init__ 并将self.max_value 用于__iter__

标签: python python-3.x generator


【解决方案1】:

首先:没有迭代器容器这样的东西。你有一个iterable

一个可迭代对象产生一个迭代器。任何迭代器也是可迭代的,但生成 自身 作为迭代器:

>>> list_iter = iter([])
>>> iter(list_iter) is list_iter
True

如果iter(ob) is ob 测试为假,则您没有迭代器。

【讨论】:

    【解决方案2】:

    您可以使用@987654321 测试您是否有一个迭代器(在next 引发StopIteration 异常时使用)与只是一个可迭代的(可能可以迭代多次) @。这是一个例子:

    from collections.abc import Iterable, Iterator
    
    def my_iterator(): 
        yield 1
    
    i = my_iterator()
    a = []
    
    isinstance(i, Iterator) # True
    isinstance(a, Iterator) # False
    

    使my_iterator()Iterator 的原因在于__next____iter__ 魔术方法的存在(顺便说一句,当您在@987654332 上调用isinstance 时,基本上在幕后发生了什么@abstract 基类是对某些魔术方法是否存在的测试)。

    请注意,迭代器也是Iterable,空列表也是如此(即,两者都有__iter__魔术方法):

    isinstance(i, Iterable) # True
    isinstance(a, Iterable) # True
    

    另请注意,as was pointed out in Martijn Pieters' answer,当您将通用 iter() 函数应用于两者时,您会得到一个迭代器:

    isinstance(iter(my_iterator()), Iterator) # True
    isinstance(iter([])), Iterator) # True
    

    []my_iterator() 之间的区别在于iter(my_iterator()) 返回自身 作为迭代器,而iter([]) 每次都生成一个新迭代器

    正如 MP 的相同答案中已经提到的,您上面的对象不是“迭代器容器”。它是一个可迭代对象,即“可迭代”。它是否“包含”某些东西并不真正相关;包含的概念由抽象基类Container 表示。 Container 可能是可迭代的,但不一定非要如此。

    【讨论】:

      猜你喜欢
      • 2011-01-04
      • 2016-04-09
      • 2014-09-28
      • 2016-03-01
      • 2018-03-20
      • 2017-02-23
      • 2018-05-16
      • 2012-08-15
      • 1970-01-01
      相关资源
      最近更新 更多