В C++ и STL, в частности, мы видим итераторы повсюду. У Python также есть итераторы, но это два совершенно разных зверя.
Итераторы C++:
- C++ имеет 5 категорий типов (случайный доступ, двунаправленный, прямой, входной, выходной)
- 2 категории операций: перепозиционирование, доступ
- Для представления (первого/последнего) диапазона требуется пара итераторов.
Итераторы Python:
- 1 категория (вперед)
- 1 категория операций (следующая())
- Исключение StopIteration в конце
Типичный протокол итерации Python:<for y
in x...
>выглядит следующим образом:
iter = x.__iter__()
try:
while 1:
y = iter.next()
...
except StopIteration: pass
Повышаю. Python предоставляет некоторые механизмы для того, чтобы итераторы C++ хорошо работали как итераторы Python. Нам нужно создать соответствующую функцию<__iter__
>из итераторов C++, совместимую с протоколом итерации Python. Например:
object get_iterator = iterator<vector<int> >();
object iter = get_iterator(v);
object first = iter.next();
Для использования в Class_<>:
.def("__iter__", iterator<vector<int> >())
диапазон
Мы можем создать итератор Python, используя функцию диапазона:
- Диапазон (начало, конец)
- range(начать, закончить)
Начало/конец может быть одним из:
- указатели данных членов
- указатели функций членов
- Адаптивный функциональный объект (используется параметр Target)
итератор
При наличии контейнера<T
>итератор представляет собой ярлык, который просто вызывает<range
>с &T::begin, &T::end.
Давайте приведем это в действие... Вот пример из гипотетического кода ускорителя частиц богона:
f = Field()
for x in f.pions:
smash(x)
for y in f.bogons:
count(y)
Теперь наш C++ Враппер:
class_<F>("Field")
.property("pions", range(&F::p_begin, &F::p_end))
.property("bogons", range(&F::b_begin, &F::b_end));
stl_input_iterator
До сих пор мы видели, как выставить итераторы C++ и диапазоны на Python. Иногда мы хотим пойти другим путем: мы хотели бы передать последовательность Python алгоритму STL или использовать ее для инициализации контейнера STL. Нам нужно сделать итератор Python похожим на итератор STL. Для этого мы используем<stl_input_iterator<>
>. Рассмотрим, как мы можем реализовать функцию, которая подвергает<std::list<int>::assign()
>Python:
template<typename T>
void list_assign(std::list<T>& l, object o) {
stl_input_iterator<T> begin(o), end;
l.assign(begin, end);
}
class_<std::list<int> >("list_int")
.def("assign", &list_assign<int>)
;
Теперь в Python мы можем назначить любую последовательность целых чисел<list_int
>объектам:
x = list_int();
x.assign([1,2,3,4,5])