Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>There are four ways to build an iterative function:</p> <ul> <li>create a generator (uses the <a href="http://docs.python.org/py3k/reference/expressions.html#yield-expressions">yield keyword</a>)</li> <li>use a generator expression (<a href="http://docs.python.org/py3k/reference/expressions.html#generator-expressions">genexp</a>)</li> <li>create an iterator (defines <a href="http://docs.python.org/py3k/library/stdtypes.html?highlight=__iter__#iterator-types"><code>__iter__</code> and <code>__next__</code></a> (or <code>next</code> in Python 2.x))</li> <li>create a function that Python can iterate over on its own (<a href="http://docs.python.org/py3k/reference/datamodel.html?highlight=__getitem__#object.__getitem__">defines <code>__getitem__</code></a>)</li> </ul> <p>Examples:</p> <pre><code># generator def uc_gen(text): for char in text: yield char.upper() # generator expression def uc_genexp(text): return (char.upper() for char in text) # iterator protocol class uc_iter(): def __init__(self, text): self.text = text self.index = 0 def __iter__(self): return self def __next__(self): try: result = self.text[self.index].upper() except IndexError: raise StopIteration self.index += 1 return result # getitem method class uc_getitem(): def __init__(self, text): self.text = text def __getitem__(self, index): result = self.text[index].upper() return result </code></pre> <p>To see all four methods in action:</p> <pre><code>for iterator in uc_gen, uc_genexp, uc_iter, uc_getitem: for ch in iterator('abcde'): print ch, print </code></pre> <p>Which results in:</p> <pre><code>A B C D E A B C D E A B C D E A B C D E </code></pre> <p><strong>Note</strong>:</p> <p>The two generator types (<code>uc_gen</code> and <code>uc_genexp</code>) cannot be <code>reversed()</code>; the plain iterator (<code>uc_iter</code>) would need the <code>__reversed__</code> magic method (which must return a new iterator that goes backwards); and the getitem iteratable (<code>uc_getitem</code>) must have the <code>__len__</code> magic method:</p> <pre><code> # for uc_iter def __reversed__(self): return reversed(self.text) # for uc_getitem def __len__(self) return len(self.text) </code></pre> <hr> <p>To answer Colonel Panic's secondary question about an infinite lazily evaluated iterator, here are those examples, using each of the four methods above:</p> <pre><code># generator def even_gen(): result = 0 while True: yield result result += 2 # generator expression def even_genexp(): return (num for num in even_gen()) # or even_iter or even_getitem # not much value under these circumstances # iterator protocol class even_iter(): def __init__(self): self.value = 0 def __iter__(self): return self def __next__(self): next_value = self.value self.value += 2 return next_value # getitem method class even_getitem(): def __getitem__(self, index): return index * 2 import random for iterator in even_gen, even_genexp, even_iter, even_getitem: limit = random.randint(15, 30) count = 0 for even in iterator(): print even, count += 1 if count &gt;= limit: break print </code></pre> <p>Which results in (at least for my sample run):</p> <pre><code>0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload