2024-10-01 09:21:46 发布
网友
刚刚在pep424(https://www.python.org/dev/peps/pep-0424/)中为迭代器找到了这个很棒的__length_hint__()方法。真 的!一种在不耗尽迭代器的情况下获得迭代器长度的方法。在
__length_hint__()
我的问题:
编辑:顺便说一句,我看到__length__hint__()从当前位置到结尾都在计数。i、 部分消耗的迭代器将报告剩余长度。有趣。在
__length__hint__()
Wow! A way to get the iterator length without exhausting the iterator.
不。这是一种获得关于长度的模糊提示的方法。没有要求它在任何方面都是准确的。在
Is there a simple explanation how does this magic work?
迭代器实现了一个__length_hint__方法,该方法使用某种特定于迭代器的信息来猜测它将输出多少元素。这个猜测可能相当不错,也可能糟糕透顶。例如,列表迭代器知道它在列表中的位置以及列表的长度,因此它可以报告列表中还剩下多少元素。在
__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__方法。在
zip
在生成器的例子中,我不认为有一个简单或自动的方法来实现它,因为如果你给我一个任意的生成器,我不知道它是怎么做的,我怎么能确定它是有限的还是不是有限的??我需要看一下代码,如果使用其他函数,我需要看看这些函数,以及它们是如何被调用的。。。它很快就会变得一团糟,所以对于一种自动的方式,所需的努力看起来比回报要大得多
在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等)有这样的特性,因为它们是这样做的
由于Conatiner_Iterator可以访问它知道的容器的所有相关信息,因此它可以给出有意义的提示,并且可以简单到
Conatiner_Iterator
def __length_hint__(self): return len(self.data) - self.i
这样做的目的基本上只是为了在Cython/C代码中更高效地分配内存。例如,假设Cython模块公开了一个函数,该函数接受自定义MyNetworkConnection()对象的iterable,并且在内部需要为数据结构创建和分配内存,以便在Cython/C代码中表示它们。如果我们能粗略估计迭代器中的项目数,我们就可以在一次操作中分配足够大的内存板,以最小的调整大小来容纳所有这些项目。在
MyNetworkConnection()
如果实现了__len__(),我们就知道确切的长度,并可以将其用于内存分配。但通常情况下,我们并不知道确切的长度,所以这个估计值通过给我们一个“大概的数字”来帮助我们提高性能。在
__len__()
它在纯Python代码中当然也很有用,例如,可能是一个面向用户的操作完成时间估计?在
对于问题2,好吧,这是一个暗示,所以你不能指望它是准确的。如果提示太低,您仍必须考虑分配新内存,如果提示太高,则必须清理内存。我个人没有意识到其他限制或潜在的问题。在
对于问题3,我看不出它为什么不适用于生成器,因为生成器是迭代器:
>>> import collections >>> def my_generator(): yield >>> gen = my_generator() >>> isinstance(gen, collections.Iterator) True
不。这是一种获得关于长度的模糊提示的方法。没有要求它在任何方面都是准确的。在
迭代器实现了一个
__length_hint__
方法,该方法使用某种特定于迭代器的信息来猜测它将输出多少元素。这个猜测可能相当不错,也可能糟糕透顶。例如,列表迭代器知道它在列表中的位置以及列表的长度,因此它可以报告列表中还剩下多少元素。在如果迭代器没有足够的信息来猜测它何时会用完,它就不能实现有用的
__length_hint__
。例如,这就是为什么发电机没有。无限迭代器也不能实现有用的__length_hint__
,因为没有办法发出无限长的信号。在zip
实例和生成器都是迭代器。但是,zip
和生成器类型都没有提供__length_hint__
方法。在在生成器的例子中,我不认为有一个简单或自动的方法来实现它,因为如果你给我一个任意的生成器,我不知道它是怎么做的,我怎么能确定它是有限的还是不是有限的??我需要看一下代码,如果使用其他函数,我需要看看这些函数,以及它们是如何被调用的。。。它很快就会变得一团糟,所以对于一种自动的方式,所需的努力看起来比回报要大得多
在
zip
的情况下,我不知道它为什么没有它,看起来很容易检查每个元素的每个提示并返回其中的最小值,也许他们没有添加它,因为你可以给它生成器,而且没有理由从它们那里得到提示?在所以在迭代器中可能更好,因为它们是用iterator protocol生成的
因此,在这里添加
^{pr2}$__length_hint__
函数的逻辑是比较容易的,这就是为什么内置容器(list、tuple、str、set等)有这样的特性,因为它们是这样做的由于
Conatiner_Iterator
可以访问它知道的容器的所有相关信息,因此它可以给出有意义的提示,并且可以简单到这样做的目的基本上只是为了在Cython/C代码中更高效地分配内存。例如,假设Cython模块公开了一个函数,该函数接受自定义
MyNetworkConnection()
对象的iterable,并且在内部需要为数据结构创建和分配内存,以便在Cython/C代码中表示它们。如果我们能粗略估计迭代器中的项目数,我们就可以在一次操作中分配足够大的内存板,以最小的调整大小来容纳所有这些项目。在如果实现了
__len__()
,我们就知道确切的长度,并可以将其用于内存分配。但通常情况下,我们并不知道确切的长度,所以这个估计值通过给我们一个“大概的数字”来帮助我们提高性能。在它在纯Python代码中当然也很有用,例如,可能是一个面向用户的操作完成时间估计?在
对于问题2,好吧,这是一个暗示,所以你不能指望它是准确的。如果提示太低,您仍必须考虑分配新内存,如果提示太高,则必须清理内存。我个人没有意识到其他限制或潜在的问题。在
对于问题3,我看不出它为什么不适用于生成器,因为生成器是迭代器:
相关问题 更多 >
编程相关推荐