title: How does ThreadPoolExecutor().map differ from ThreadPoolExecutor().submit?
body: <p>I was just very confused by some code that I wrote. I was surprised to discover that:</p>
  
  <pre><code>with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
      results = list(executor.map(f, iterable))
  </code></pre>
  
  <p>and </p>
  
  <pre><code>with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
      results = list(map(lambda x: executor.submit(f, x), iterable))
  </code></pre>
  
  <p>produce different results. The first one produces a list of whatever type <code>f</code> returns, the second produces a list of <code>concurrent.futures.Future</code> objects that then need to be evaluated with their <code>result()</code> method in order to get the value that <code>f</code> returned. </p>
  
  <p>My main concern is that this means that <code>executor.map</code> can't take advantage of <code>concurrent.futures.as_completed</code>, which seems like an extremely convenient way to evaluate the results of some long-running calls to a database that I'm making as they become available. </p>
  
  <p>I'm not at all clear on how <code>concurrent.futures.ThreadPoolExecutor</code> objects work -- naively, I would prefer the (somewhat more verbose):</p>
  
  <pre><code>with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
      result_futures = list(map(lambda x: executor.submit(f, x), iterable))
      results = [f.result() for f in futures.as_completed(result_futures)]
  </code></pre>
  
  <p>over the more concise <code>executor.map</code> in order to take advantage of a possible gain in performance. Am I wrong to do so?</p>