<p>如果<code>lst</code>的长度是<code>lines</code>的乘法,则下面的代码可以工作</p>
<pre><code>>>> lst = [1, 2, 3, 4, 5, 6]
>>> lines = 3
>>> zip(*zip(*[iter(lst)]*lines))
[(1, 4), (2, 5), (3, 6)]
</code></pre>
<p>这个魔法来自wim提到的<code>grouper</code></p>
<h2>解释魔法</h2>
<p>有一个值列表</p>
<pre><code>>>> lst = [1,2,3,4,5,6]
</code></pre>
<p>对列表值创建迭代器:</p>
<pre><code>>>> iter(lst)
<listiterator at 0x7f641480d490>
</code></pre>
<p>注意:迭代器能够从自身逐项生成,在本例中,它可以从<code>lst</code>中逐项生成</p>
<p>创建包含一个迭代器的列表:</p>
<pre><code>>>> [iter(lst)]
[<listiterator at 0x7f641480d750>]
</code></pre>
<p>列表是可变结构,因此即使从多个变量引用,它仍然引用
内存中相同的数据结构。如果这些引用中的任何一个在内部使用迭代器,那么迭代器
对该列表的所有引用都进行了修改</p>
<p>现在创建列表的乘法,乘以期望的行数</p>
<pre><code>>>> [iter(lst)] * 3
[<listiterator at 0x7f641480dc50>,
<listiterator at 0x7f641480dc50>,
<listiterator at 0x7f641480dc50>]
</code></pre>
<p>注意,所有迭代器都显示相同的地址,此列表中的所有三项都引用
到同一迭代器</p>
<p>现在是filan步骤,将所有内容压缩到一起:</p>
<pre><code>>>> zip(*[iter(lst)] * 3)
[(1, 2, 3), (4, 5, 6)]
</code></pre>
<p>可以重写为:</p>
<pre><code>zip(*[<listiterator at 0x7f641480dc50>, <listiterator at 0x7f641480dc50>, <listiterator at 0x7f641480dc50>])
</code></pre>
<p>什么(通过<code>*</code>取消引用)转换为:</p>
<pre><code>>>> zip(<listiterator at 0x7f641480dc50>, <listiterator at 0x7f641480dc50>, <listiterator at 0x7f641480dc50>)
[(1, 2, 3), (4, 5, 6)]
</code></pre>
<p><code>zip</code>的工作方式是,它要求每个迭代器提供一个值并创建一个元组
从这3个值。诀窍是,每次从迭代器请求一个值时,都会从
所有引用,所以下次它询问任何迭代器时,将出现下一个值</p>
<p>最后一步是做最后的拉链:</p>
<pre><code>zip(*[(1, 2, 3), (4, 5, 6)])
</code></pre>
<p>转换为:</p>
<pre><code>zip((1, 2, 3), (4, 5, 6))
</code></pre>
<p>结果是:</p>
<pre><code>[(1, 4), (2, 5), (3, 6)]
</code></pre>