<html> <head> <!-- Generated by the Spirit (http://spirit.sf.net) QuickDoc --> <title>Iterators</title> <link rel="stylesheet" href="theme/style.css" type="text/css"> <link rel="prev" href="using_the_interpreter.html"> <link rel="next" href="exception_translation.html"> </head> <body> <table width="100%" height="48" border="0" cellspacing="2"> <tr> <td><img src="theme/c%2B%2Bboost.gif"> </td> <td width="85%"> <font size="6" face="Verdana, Arial, Helvetica, sans-serif"><b>Iterators</b></font> </td> </tr> </table> <br> <table border="0"> <tr> <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td> <td width="30"><a href="using_the_interpreter.html"><img src="theme/l_arr.gif" border="0"></a></td> <td width="20"><a href="exception_translation.html"><img src="theme/r_arr.gif" border="0"></a></td> </tr> </table> <p> In C++, and STL in particular, we see iterators everywhere. Python also has iterators, but these are two very different beasts.</p> <p> <b>C++ iterators:</b></p> <ul><li>C++ has 5 type categories (random-access, bidirectional, forward, input, output)</li><li>There are 2 Operation categories: reposition, access</li><li>A pair of iterators is needed to represent a (first/last) range.</li></ul><p> <b>Python Iterators:</b></p> <ul><li>1 category (forward)</li><li>1 operation category (next())</li><li>Raises StopIteration exception at end</li></ul><p> The typical Python iteration protocol: <tt><b>for y in x...</b></tt> is as follows:</p> <code><pre> <span class=identifier>iter </span><span class=special>= </span><span class=identifier>x</span><span class=special>.</span><span class=identifier>__iter__</span><span class=special>() </span>##<span class=identifier>get </span><span class=identifier>iterator </span><span class=keyword>try</span><span class=special>: </span><span class=keyword>while </span><span class=number>1</span><span class=special>: </span><span class=identifier>y </span><span class=special>= </span><span class=identifier>iter</span><span class=special>.</span><span class=identifier>next</span><span class=special>() </span>##<span class=identifier>get </span><span class=identifier>each </span><span class=identifier>item </span><span class=special>... </span>##<span class=identifier>process </span><span class=identifier>y </span><span class=identifier>except </span><span class=identifier>StopIteration</span><span class=special>: </span><span class=identifier>pass </span>##<span class=identifier>iterator </span><span class=identifier>exhausted </span></pre></code> <p> Boost.Python provides some mechanisms to make C++ iterators play along nicely as Python iterators. What we need to do is to produce appropriate __iter__ function from C++ iterators that is compatible with the Python iteration protocol. For example:</p> <code><pre> <span class=identifier>object </span><span class=identifier>get_iterator </span><span class=special>= </span><span class=identifier>iterator</span><span class=special><</span><span class=identifier>vector</span><span class=special><</span><span class=keyword>int</span><span class=special>> >(); </span><span class=identifier>object </span><span class=identifier>iter </span><span class=special>= </span><span class=identifier>get_iterator</span><span class=special>(</span><span class=identifier>v</span><span class=special>); </span><span class=identifier>object </span><span class=identifier>first </span><span class=special>= </span><span class=identifier>iter</span><span class=special>.</span><span class=identifier>next</span><span class=special>(); </span></pre></code> <p> Or for use in class_<>:</p> <code><pre> <span class=special>.</span><span class=identifier>def</span><span class=special>(</span><span class=string>"__iter__"</span><span class=special>, </span><span class=identifier>iterator</span><span class=special><</span><span class=identifier>vector</span><span class=special><</span><span class=keyword>int</span><span class=special>> >()) </span></pre></code> <p> <b>range</b></p> <p> We can create a Python savvy iterator using the range function:</p> <ul><li>range(start, finish)</li><li>range<Policies,Target>(start, finish)</li></ul><p> Here, start/finish may be one of:</p> <ul><li>member data pointers</li><li>member function pointers</li><li>adaptable function object (use Target parameter)</li></ul><p> <b>iterator</b></p> <ul><li>iterator<T, Policies>()</li></ul><p> Given a container <tt>T</tt>, iterator is a shortcut that simply calls <tt>range</tt> with &T::begin, &T::end.</p> <p> Let's put this into action... Here's an example from some hypothetical bogon Particle accelerator code:</p> <code><pre> <span class=identifier>f </span><span class=special>= </span><span class=identifier>Field</span><span class=special>() </span><span class=keyword>for </span><span class=identifier>x </span><span class=identifier>in </span><span class=identifier>f</span><span class=special>.</span><span class=identifier>pions</span><span class=special>: </span><span class=identifier>smash</span><span class=special>(</span><span class=identifier>x</span><span class=special>) </span><span class=keyword>for </span><span class=identifier>y </span><span class=identifier>in </span><span class=identifier>f</span><span class=special>.</span><span class=identifier>bogons</span><span class=special>: </span><span class=identifier>count</span><span class=special>(</span><span class=identifier>y</span><span class=special>) </span></pre></code> <p> Now, our C++ Wrapper:</p> <code><pre> <span class=identifier>class_</span><span class=special><</span><span class=identifier>F</span><span class=special>>(</span><span class=string>"Field"</span><span class=special>) .</span><span class=identifier>property</span><span class=special>(</span><span class=string>"pions"</span><span class=special>, </span><span class=identifier>range</span><span class=special>(&</span><span class=identifier>F</span><span class=special>::</span><span class=identifier>p_begin</span><span class=special>, &</span><span class=identifier>F</span><span class=special>::</span><span class=identifier>p_end</span><span class=special>)) .</span><span class=identifier>property</span><span class=special>(</span><span class=string>"bogons"</span><span class=special>, </span><span class=identifier>range</span><span class=special>(&</span><span class=identifier>F</span><span class=special>::</span><span class=identifier>b_begin</span><span class=special>, &</span><span class=identifier>F</span><span class=special>::</span><span class=identifier>b_end</span><span class=special>)); </span></pre></code> <table border="0"> <tr> <td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td> <td width="30"><a href="using_the_interpreter.html"><img src="theme/l_arr.gif" border="0"></a></td> <td width="20"><a href="exception_translation.html"><img src="theme/r_arr.gif" border="0"></a></td> </tr> </table> <br> <hr size="1"><p class="copyright">Copyright © 2002-2003 David Abrahams<br>Copyright © 2002-2003 Joel de Guzman<br><br> <font size="2">Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose. </font> </p> </body> </html>