<p>有没有一种统一的方法可以知道迭代是否会消耗iterable对象?在</p>
<p>假设您有一个函数<code>crunch</code>,它请求一个iterable对象作为参数,并多次使用它。比如:</p>
<pre><code>def crunch (vals):
for v in vals:
chomp(v)
for v in vals:
yum(v)
</code></pre>
<p>(注意:合并两个<code>for</code>循环不是一个选项)。在</p>
<p>如果使用不是列表的iterable调用函数,则会出现问题。在下面的调用中,<code>yum</code>函数从不执行:</p>
^{pr2}$
<p>原则上,我们可以通过如下重新定义<code>crunch</code>函数来解决此问题:</p>
<pre><code>def crunch (vals):
vals = list(vals)
for v in vals:
chomp(v)
for v in vals:
yum(v)
</code></pre>
<p>但是如果对<code>crunch</code>的调用是:</p>
<pre><code>hugeList = list(longDataStream)
crunch(hugeList)
</code></pre>
<p>我们可以通过如下定义<code>crunch</code>来解决此问题:</p>
<pre><code>def crunch (vals):
if type(vals) is not list:
vals = list(vals)
for v in vals:
chomp(v)
for v in vals:
yum(v)
</code></pre>
<p>但是仍然存在调用代码将数据存储在</p>
<ul>
<li>无法消费</li>
<li>不是列表</li>
</ul>
<p>例如:</p>
<pre><code>from collections import deque
hugeDeque = deque(longDataStream)
crunch(hugeDeque)
</code></pre>
<p>最好有一个<code>isconsumable</code>谓词,这样我们就可以像这样定义<code>crunch</code>:</p>
<pre><code>def crunch (vals):
if isconsumable(vals):
vals = list(vals)
for v in vals:
chomp(v)
for v in vals:
yum(v)
</code></pre>
<p>这个问题有解决办法吗?在</p>
<pre><code>def crunch (vals):
vals1, vals2 = itertools.tee(vals, 2)
for v in vals1:
chomp(v)
for v in vals2:
yum(v)
</code></pre>
<p>在这种情况下,<code>tee</code>将在内部存储{<cd2>}的完整性,因为一个迭代器在另一个迭代器启动之前完成</p>