<p>我非常喜欢发电机和理解,但在这种情况下,它们似乎不是正确的方法,因为:</p>
<ol>
<li>要计算列表的<code>min</code>和<code>max</code></li>
<li>你的单子很大</li>
</ol>
<p>如果您只想计算<code>min</code>或<code>max</code>中的一个,则可以对其使用min/max函数。但是由于两者都需要,因此必须循环遍历列表两次,先提取最小值,然后提取最大值,例如:</p>
<pre><code>x_min = min(points)
x_max = max(points)
</code></pre>
<p>我们来玩玩计时吧。首先调用列表中的min和max:</p>
<pre><code>>>> import timeit
>>> def with_gens(l):
... return min(l), max(l)
...
>>> timeit.timeit('with_gens(range(6000000))', 'from __main__ import with_gens', number=5)
1.7451060887015188
</code></pre>
<p>现在只循环一次,使用您的代码:</p>
<pre><code>>>> def with_loop2(l):
... x_max = float('+inf')
... x_min = float('-inf')
... for el in l:
... x_min = min(x_min, el)
... x_max = max(x_max, el)
... return x_min, x_max
...
>>> timeit.timeit('with_loop2(range(6000000))', 'from __main__ import with_loop2', number=5)
11.636076105071083
</code></pre>
<p>疯了吧?</p>
<p>这种方法完全没有内存问题。但是,它在每个循环中设置<code>x_max</code>和<code>x_min</code>,这实际上是一种不必要的浪费:您只想在找到更大/更小的值时重置变量。我们可以很容易地解决这个问题。</p>
<p>所以。。。我们只循环一次,但要避免不必要的重置。</p>
<pre><code>>>> def with_loop(l):
... x_min = float('-inf')
... x_max = float('+inf')
... for el in l:
... if el < x_min:
... x_min = el
... elif el > x_max:
... x_max = el
... return x_min, x_max
...
>>> timeit.timeit('with_loop(range(6000000))', 'from __main__ import with_loop', number=5)
3.961046726963332
</code></pre>
<p><strong>哦,惊喜</strong></p>
<p>虽然只循环一次的算法在纸上更有效,但它被<code>min</code>和<code>max</code>的内部优化击败。此外,在每个循环中设置var与仅在必要时设置var之间的差异是巨大的。<em>你永远不会停止学习。</p>