PEP 424\uUu length_uhint_Uu()有没有方法可以对生成器或拉链进行同样的操作?

2024-10-01 09:21:46 发布

您现在位置:Python中文网/ 问答频道 /正文

刚刚在pep424(https://www.python.org/dev/peps/pep-0424/)中为迭代器找到了这个很棒的__length_hint__()方法。真 的!一种在不耗尽迭代器的情况下获得迭代器长度的方法。在

我的问题:

  1. 有没有一个简单的解释这个魔术是怎么起作用的?我只是好奇。在
  2. 是否存在一些限制和不起作用的情况?(“提示”听起来有点可疑)。在
  3. 有没有办法得到拉链和发电机的提示?或者它只是迭代器的基础?在

编辑:顺便说一句,我看到__length__hint__()从当前位置到结尾都在计数。i、 部分消耗的迭代器将报告剩余长度。有趣。在


Tags: 方法httpsorgdevwww魔术情况length
3条回答

Wow! A way to get the iterator length without exhausting the iterator.

不。这是一种获得关于长度的模糊提示的方法。没有要求它在任何方面都是准确的。在

Is there a simple explanation how does this magic work?

迭代器实现了一个__length_hint__方法,该方法使用某种特定于迭代器的信息来猜测它将输出多少元素。这个猜测可能相当不错,也可能糟糕透顶。例如,列表迭代器知道它在列表中的位置以及列表的长度,因此它可以报告列表中还剩下多少元素。在

Are there limitations and cases where it wouldn't work?

如果迭代器没有足够的信息来猜测它何时会用完,它就不能实现有用的__length_hint__。例如,这就是为什么发电机没有。无限迭代器也不能实现有用的__length_hint__,因为没有办法发出无限长的信号。在

Is there a way to get the hint for zips and generators as well? Or is it something fundamental only to iterators?

zip实例和生成器都是迭代器。但是,zip和生成器类型都没有提供__length_hint__方法。在

Is there a way to get the hint for zips and generators as well? Or is it something fundamental only to iterators?

在生成器的例子中,我不认为有一个简单或自动的方法来实现它,因为如果你给我一个任意的生成器,我不知道它是怎么做的,我怎么能确定它是有限的还是不是有限的??我需要看一下代码,如果使用其他函数,我需要看看这些函数,以及它们是如何被调用的。。。它很快就会变得一团糟,所以对于一种自动的方式,所需的努力看起来比回报要大得多

zip的情况下,我不知道它为什么没有它,看起来很容易检查每个元素的每个提示并返回其中的最小值,也许他们没有添加它,因为你可以给它生成器,而且没有理由从它们那里得到提示?在

所以在迭代器中可能更好,因为它们是用iterator protocol生成的

class MyIterator:
    def __iter__(self):
        return self
    def __next__(self):
        ...
        if condition_for_more_values:
            ...
            return next_value
        else:
            raise StopIteration

因此,在这里添加__length_hint__函数的逻辑是比较容易的,这就是为什么内置容器(list、tuple、str、set等)有这样的特性,因为它们是这样做的

^{pr2}$

由于Conatiner_Iterator可以访问它知道的容器的所有相关信息,因此它可以给出有意义的提示,并且可以简单到

    def __length_hint__(self):
        return len(self.data) - self.i

这样做的目的基本上只是为了在Cython/C代码中更高效地分配内存。例如,假设Cython模块公开了一个函数,该函数接受自定义MyNetworkConnection()对象的iterable,并且在内部需要为数据结构创建和分配内存,以便在Cython/C代码中表示它们。如果我们能粗略估计迭代器中的项目数,我们就可以在一次操作中分配足够大的内存板,以最小的调整大小来容纳所有这些项目。在

如果实现了__len__(),我们就知道确切的长度,并可以将其用于内存分配。但通常情况下,我们并不知道确切的长度,所以这个估计值通过给我们一个“大概的数字”来帮助我们提高性能。在

它在纯Python代码中当然也很有用,例如,可能是一个面向用户的操作完成时间估计?在

对于问题2,好吧,这是一个暗示,所以你不能指望它是准确的。如果提示太低,您仍必须考虑分配新内存,如果提示太高,则必须清理内存。我个人没有意识到其他限制或潜在的问题。在

对于问题3,我看不出它为什么不适用于生成器,因为生成器是迭代器

>>> import collections
>>> def my_generator(): yield
>>> gen = my_generator()
>>> isinstance(gen, collections.Iterator)
True

相关问题 更多 >