• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<html>
2<head>
3<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
4<title>Iterators</title>
5<link rel="stylesheet" href="../../boostbook.css" type="text/css">
6<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
7<link rel="home" href="../index.html" title="Boost.Python Tutorial">
8<link rel="up" href="../index.html" title="Boost.Python Tutorial">
9<link rel="prev" href="embedding.html" title="Embedding">
10<link rel="next" href="exception.html" title="Exception Translation">
11</head>
12<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
13<table cellpadding="2" width="100%"><tr><td valign="top"><img alt="" width="" height="" src="../../images/boost.png"></td></tr></table>
14<hr>
15<div class="spirit-nav">
16<a accesskey="p" href="embedding.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="exception.html"><img src="../../images/next.png" alt="Next"></a>
17</div>
18<div class="section">
19<div class="titlepage"><div><div><h2 class="title" style="clear: both">
20<a name="tutorial.iterators"></a><a class="link" href="iterators.html" title="Iterators">Iterators</a>
21</h2></div></div></div>
22<p>
23      In C++, and STL in particular, we see iterators everywhere. Python also has
24      iterators, but these are two very different beasts.
25    </p>
26<p>
27      <span class="bold"><strong>C++ iterators:</strong></span>
28    </p>
29<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
30<li class="listitem">
31          C++ has 5 type categories (random-access, bidirectional, forward, input,
32          output)
33        </li>
34<li class="listitem">
35          There are 2 Operation categories: reposition, access
36        </li>
37<li class="listitem">
38          A pair of iterators is needed to represent a (first/last) range.
39        </li>
40</ul></div>
41<p>
42      <span class="bold"><strong>Python Iterators:</strong></span>
43    </p>
44<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
45<li class="listitem">
46          1 category (forward)
47        </li>
48<li class="listitem">
49          1 operation category (next())
50        </li>
51<li class="listitem">
52          Raises StopIteration exception at end
53        </li>
54</ul></div>
55<p>
56      The typical Python iteration protocol: <code class="literal"><span class="bold"><strong>for y
57      in x...</strong></span></code> is as follows:
58    </p>
59<pre class="programlisting"><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="comment"># get iterator</span>
60<span class="keyword">try</span><span class="special">:</span>
61    <span class="keyword">while</span> <span class="number">1</span><span class="special">:</span>
62    <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="comment"># get each item</span>
63    <span class="special">...</span>                     <span class="comment"># process y</span>
64<span class="keyword">except</span> <span class="identifier">StopIteration</span><span class="special">:</span> <span class="keyword">pass</span>  <span class="comment"># iterator exhausted</span>
65</pre>
66<p>
67      Boost.Python provides some mechanisms to make C++ iterators play along nicely
68      as Python iterators. What we need to do is to produce appropriate <code class="computeroutput"><span class="identifier">__iter__</span></code> function from C++ iterators that
69      is compatible with the Python iteration protocol. For example:
70    </p>
71<pre class="programlisting"><span class="identifier">object</span> <span class="identifier">get_iterator</span> <span class="special">=</span> <span class="identifier">iterator</span><span class="special">&lt;</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="special">&gt;();</span>
72<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>
73<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>
74</pre>
75<p>
76      Or for use in class_&lt;&gt;:
77    </p>
78<pre class="programlisting"><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">&lt;</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="special">&gt;())</span>
79</pre>
80<p>
81      <span class="bold"><strong>range</strong></span>
82    </p>
83<p>
84      We can create a Python savvy iterator using the range function:
85    </p>
86<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
87<li class="listitem">
88          range(start, finish)
89        </li>
90<li class="listitem">
91          range&lt;Policies,Target&gt;(start, finish)
92        </li>
93</ul></div>
94<p>
95      Here, start/finish may be one of:
96    </p>
97<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
98<li class="listitem">
99          member data pointers
100        </li>
101<li class="listitem">
102          member function pointers
103        </li>
104<li class="listitem">
105          adaptable function object (use Target parameter)
106        </li>
107</ul></div>
108<p>
109      <span class="bold"><strong>iterator</strong></span>
110    </p>
111<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
112          iterator&lt;T, Policies&gt;()
113        </li></ul></div>
114<p>
115      Given a container <code class="literal">T</code>, iterator is a shortcut that simply
116      calls <code class="literal">range</code> with &amp;T::begin, &amp;T::end.
117    </p>
118<p>
119      Let's put this into action... Here's an example from some hypothetical bogon
120      Particle accelerator code:
121    </p>
122<pre class="programlisting"><span class="identifier">f</span> <span class="special">=</span> <span class="identifier">Field</span><span class="special">()</span>
123<span class="keyword">for</span> <span class="identifier">x</span> <span class="keyword">in</span> <span class="identifier">f</span><span class="special">.</span><span class="identifier">pions</span><span class="special">:</span>
124    <span class="identifier">smash</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span>
125<span class="keyword">for</span> <span class="identifier">y</span> <span class="keyword">in</span> <span class="identifier">f</span><span class="special">.</span><span class="identifier">bogons</span><span class="special">:</span>
126    <span class="identifier">count</span><span class="special">(</span><span class="identifier">y</span><span class="special">)</span>
127</pre>
128<p>
129      Now, our C++ Wrapper:
130    </p>
131<pre class="programlisting"><span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">&gt;(</span><span class="string">"Field"</span><span class="special">)</span>
132    <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">(&amp;</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">p_begin</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">p_end</span><span class="special">))</span>
133    <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">(&amp;</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_begin</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">F</span><span class="special">::</span><span class="identifier">b_end</span><span class="special">));</span>
134</pre>
135<p>
136      <span class="bold"><strong>stl_input_iterator</strong></span>
137    </p>
138<p>
139      So far, we have seen how to expose C++ iterators and ranges to Python. Sometimes
140      we wish to go the other way, though: we'd like to pass a Python sequence to
141      an STL algorithm or use it to initialize an STL container. We need to make
142      a Python iterator look like an STL iterator. For that, we use <code class="computeroutput"><span class="identifier">stl_input_iterator</span><span class="special">&lt;&gt;</span></code>.
143      Consider how we might implement a function that exposes <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;::</span><span class="identifier">assign</span><span class="special">()</span></code> to Python:
144    </p>
145<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
146<span class="keyword">void</span> <span class="identifier">list_assign</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;&amp;</span> <span class="identifier">l</span><span class="special">,</span> <span class="identifier">object</span> <span class="identifier">o</span><span class="special">)</span> <span class="special">{</span>
147    <span class="comment">// Turn a Python sequence into an STL input range</span>
148    <span class="identifier">stl_input_iterator</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="identifier">begin</span><span class="special">(</span><span class="identifier">o</span><span class="special">),</span> <span class="identifier">end</span><span class="special">;</span>
149    <span class="identifier">l</span><span class="special">.</span><span class="identifier">assign</span><span class="special">(</span><span class="identifier">begin</span><span class="special">,</span> <span class="identifier">end</span><span class="special">);</span>
150<span class="special">}</span>
151
152<span class="comment">// Part of the wrapper for list&lt;int&gt;</span>
153<span class="identifier">class_</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="special">&gt;(</span><span class="string">"list_int"</span><span class="special">)</span>
154    <span class="special">.</span><span class="identifier">def</span><span class="special">(</span><span class="string">"assign"</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">list_assign</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;)</span>
155    <span class="comment">// ...</span>
156    <span class="special">;</span>
157</pre>
158<p>
159      Now in Python, we can assign any integer sequence to <code class="computeroutput"><span class="identifier">list_int</span></code>
160      objects:
161    </p>
162<pre class="programlisting"><span class="identifier">x</span> <span class="special">=</span> <span class="identifier">list_int</span><span class="special">();</span>
163<span class="identifier">x</span><span class="special">.</span><span class="identifier">assign</span><span class="special">([</span><span class="number">1</span><span class="special">,</span><span class="number">2</span><span class="special">,</span><span class="number">3</span><span class="special">,</span><span class="number">4</span><span class="special">,</span><span class="number">5</span><span class="special">])</span>
164</pre>
165</div>
166<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
167<td align="left"></td>
168<td align="right"><div class="copyright-footer">Copyright © 2002-2005 Joel
169      de Guzman, David Abrahams<p>
170        Distributed under the Boost Software License, Version 1.0. (See accompanying
171        file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>
172      </p>
173</div></td>
174</tr></table>
175<hr>
176<div class="spirit-nav">
177<a accesskey="p" href="embedding.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="exception.html"><img src="../../images/next.png" alt="Next"></a>
178</div>
179</body>
180</html>
181