title: Does itertools.product evaluate its arguments lazily?
body: <p>The following never prints anything in Python 3.6</p>
  
  <pre><code>from itertools import product, count
  
  for f in product(count(), [1,2]): 
      print(f)
  </code></pre>
  
  <p>Instead, it just sits there and burns CPU. The issue seems to be that <code>product</code> never returns an iterator if it's over an infinite space because it evaluates the full <code>product</code> first. This is surprising given that the <code>product</code> is supposed to be a generator.</p>
  
  <p>I would have expected this to start counting up (to infinity), something like the behavior of this generator (taken <a href="https://docs.python.org/3.6/library/itertools.html#itertools.product" rel="noreferrer">directly from the docs</a>):</p>
  
  <pre><code>for tup in ((x,y) for x in count() for y in [1,2]):
      print(tup)
  </code></pre>
  
  <p>But whereas my generator starts counting immediately, the one using <code>product</code> never counts at all.</p>
  
  <p>Other tools in <code>itertools</code> do what I'd expect. For example, the following:</p>
  
  <pre><code>for f in takewhile(lambda x: True, count()): 
      print(f)
  </code></pre>
  
  <p>will print a stream of numbers because <code>takewhile</code> is lazy.</p>