Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

Click here to view the latest version of this page.
PrevUpHomeNext

Iterators

In C++, and STL in particular, we see iterators everywhere. Python also has iterators, but these are two very different beasts.

C++ iterators:

Python Iterators:

The typical Python iteration protocol: for y in x... is as follows:

iter = x.__iter__()         # get iterator
try:
    while 1:
    y = iter.next()         # get each item
    ...                     # process y
except StopIteration: pass  # iterator exhausted

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:

object get_iterator = iterator<vector<int> >();
object iter = get_iterator(v);
object first = iter.next();

Or for use in class_<>:

.def("__iter__", iterator<vector<int> >())

range

We can create a Python savvy iterator using the range function:

Here, start/finish may be one of:

iterator

Given a container T, iterator is a shortcut that simply calls range with &T::begin, &T::end.

Let's put this into action... Here's an example from some hypothetical bogon Particle accelerator code:

f = Field()
for x in f.pions:
    smash(x)
for y in f.bogons:
    count(y)

Now, our C++ Wrapper:

class_<F>("Field")
    .property("pions", range(&F::p_begin, &F::p_end))
    .property("bogons", range(&F::b_begin, &F::b_end));

stl_input_iterator

So far, we have seen how to expose C++ iterators and ranges to Python. Sometimes we wish to go the other way, though: we'd like to pass a Python sequence to an STL algorithm or use it to initialize an STL container. We need to make a Python iterator look like an STL iterator. For that, we use stl_input_iterator<>. Consider how we might implement a function that exposes std::list<int>::assign() to Python:

template<typename T>
void list_assign(std::list<T>& l, object o) {
    // Turn a Python sequence into an STL input range
    stl_input_iterator<T> begin(o), end;
    l.assign(begin, end);
}

// Part of the wrapper for list<int>
class_<std::list<int> >("list_int")
    .def("assign", &list_assign<int>)
    // ...
    ;

Now in Python, we can assign any integer sequence to list_int objects:

x = list_int();
x.assign([1,2,3,4,5])

PrevUpHomeNext