Agu*_*guy 3 python generator python-3.x python-internals
刚刚__length_hint__()从PEP 424(https://www.python.org/dev/peps/pep-0424/)遇到了这个非常棒的迭代器方法.哇!一种获取迭代器长度而不会耗尽迭代器的方法.
我的问题:
编辑: BTW,我看到__length__hint__()从当前位置到结束的计数.即部分消耗的迭代器将报告剩余长度.有趣.
哇!一种获取迭代器长度而不会耗尽迭代器的方法.
不,这是一种模糊暗示长度可能是什么的方法.没有要求它以任何方式准确.
有一个简单的解释这个魔法是如何工作的?
迭代器实现了一种__length_hint__方法,该方法使用某种特定于迭代器的信息来猜测它将输出多少元素.这个猜测可能相当不错,或者它可能非常糟糕.例如,列表迭代器知道它在列表中的位置以及列表的长度,因此它可以报告列表中剩余的元素数量.
是否有限制和案例不起作用?
如果迭代器没有足够的信息来猜测它何时会耗尽,那么它就无法实现有用的功能__length_hint__.例如,这就是发电机没有发电机的原因.无限迭代器也无法实现有用__length_hint__,因为没有办法发出无限长的信号.
有没有办法获得拉链和发电机的提示?或者它只是迭代器的基础?
zip实例和生成器都是各种迭代器.zip但是,生成器类型都不提供__length_hint__方法.
这个问题有几个答案,但它们都有点没有抓住重点:这__length_hint__不是魔法。这是一个协议。如果一个对象没有实现该协议,那就是这样。
让我们绕道看看a + b,因为它是一个简单的例子。经营+者依赖a.__add__并b.__radd__实际做某事。int实现__add__平均算术加法 ( 1 + 2 == 3),同时list实现__add__平均内容连接 ( [1] + [2] == [1, 2])。这是因为它__add__只是一个协议,对象如果提供它就必须遵守该协议。的定义__add__基本上只是“获取另一个操作数并返回一个对象”。
没有单独的、普遍的含义+。如果操作数不提供__add__or _radd__,则 python 无能为力。
回到实际问题,这意味着什么?
有没有简单的解释一下这个魔法是如何运作的?我只是好奇。
PEP 424中列出了所有的魔法,但它基本上是:尝试len(obj)、回退到obj.__length_hint__、使用默认值。这就是全部的魔力。
在实践中,对象必须__length_hint__根据它对自身的了解来实现。例如,采用range_iterator范围向后移植或Py3.6 C 代码):
return self._stop - self._current
Run Code Online (Sandbox Code Playgroud)
在这里,迭代器知道它最多有多长,以及它提供了多少。如果它不跟踪后者,它可能仍会返回最多多长时间。无论哪种方式,它都必须使用关于自身的内部知识。
是否存在无法发挥作用的限制和情况?(“提示”听起来有点可疑)。
显然,没有实现__length_hint__或__len__不起作用的对象。从根本上来说,任何对其状态没有足够了解的对象都无法实现它。
链式生成器通常不实现它。例如,(a ** 2 for a in range(5))不会转发来自 的长度提示range。如果您考虑到可能存在任意的迭代器链,这是明智的: length_hint这只是预分配空间的优化,并且仅获取要放入该空间的内容可能会更快。
在其他情况下,这可能是根本不可能的。无限迭代器和随机迭代器都属于这一类,而且外部资源上的迭代器也属于这一类。
有没有办法同时获得 zip 和生成器的提示?或者它只是迭代器的基础知识?
如果一个对象没有实现__length_hint__,那么就没有。Zip 和发电机则不然,可能是出于上述效率原因。
另请注意,zip 和生成器对象是它们自己的迭代器。
foo = zip([1,2,3], [1,2,3])
id(foo) == id(iter(foo)) # returns True in py3.5
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
913 次 |
| 最近记录: |