title: Python: range() and non-consumable generators
body: <p>In Python 3 (2), the <code>range</code> (<code>xrange</code>) function returns a generator which yields consecutive integers, e.g.</p>
  
  <pre><code>g = range(5)
  print(g)  # Prints range(0, 5)
  t = tuple(g)
  print(t)  # Prints (0, 1, 2, 3, 4)
  </code></pre>
  
  <p>Here, <code>tuple(g)</code> constructs a tuple by looping over the generator <code>g</code> and storing each yielded number. I can also construct a generator from the tuple, e.g.</p>
  
  <pre><code># like this
  g2 = iter(t)
  t2 = tuple(g2)
  # or like this
  g3 = (n for n in t)
  t3 = tuple(g3)
  </code></pre>
  
  <p>There is however a big difference between the original <code>g</code> and the homecrafted <code>g2</code> and <code>g3</code>, which we see if we try to construct a second tuple:</p>
  
  <pre><code>tuple(g)   # Works as before
  tuple(g2)  # Produces an empty tuple !
  tuple(g3)  # Produces an empty tuple !
  </code></pre>
  
  <p>Thus <code>g2</code> and <code>g3</code> (unlike <code>g</code>) are "consumed" on iteration.</p>
  
  <p>Is there an easy way to produce custom, non-consumable generators? My guess is that neither bare generator expressions nor bare functions that <code>yield</code>s can be used.</p>