<p>除了在这里的答案中的解释外,直接找到来源是有帮助的。它重申另一个答复中的声明:</p>
<ul>
<li><code>.map()</code>按提交结果的顺序给出结果,而</li>
<li>用<a href="https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.as_completed" rel="noreferrer">^{<cd3>}</a>遍历<code>Future</code>对象列表不会保证这种顺序,因为这是<code>as_completed()</code>的本质</li>
</ul>
<hr/>
<p><code>.map()</code>在基类中定义,<a href="https://github.com/python/cpython/blob/3.7/Lib/concurrent/futures/_base.py" rel="noreferrer">^{<cd6>}</a>:</p>
<pre><code>class Executor(object):
def submit(self, fn, *args, **kwargs):
raise NotImplementedError()
def map(self, fn, *iterables, timeout=None, chunksize=1):
if timeout is not None:
end_time = timeout + time.monotonic()
fs = [self.submit(fn, *args) for args in zip(*iterables)] # <!!!!!!!!
def result_iterator():
try:
# reverse to keep finishing order
fs.reverse() # <!!!!!!!!
while fs:
# Careful not to keep a reference to the popped future
if timeout is None:
yield fs.pop().result() # <!!!!!!!!
else:
yield fs.pop().result(end_time - time.monotonic())
finally:
for future in fs:
future.cancel()
return result_iterator()
</code></pre>
<p>正如您所提到的,还有<code>.submit()</code>,它留在子类中定义,即<code>ProcessPoolExecutor</code>和<a href="https://github.com/python/cpython/blob/3.7/Lib/concurrent/futures/thread.py" rel="noreferrer">^{<cd9>}</a>,并返回一个<code>_base.Future</code>实例,您需要调用该实例才能实际执行任何操作。</p>
<p>从<code>.map()</code>开始的重要行可以归结为:</p>
<pre><code>fs = [self.submit(fn, *args) for args in zip(*iterables)]
fs.reverse()
while fs:
yield fs.pop().result()
</code></pre>
<p><code>.reverse()</code>加上<code>.pop()</code>是获得第一个提交结果(来自<code>iterables</code>)的方法,该结果首先被生成,第二个提交结果其次被生成,依此类推。结果迭代器的元素不是<code>Future</code>s;它们本身就是实际的结果。</p>