6.5 Using OEChem C++ Iterators Directly

The standard way of processing each item or member of a set or collection in OEChem is by use of a C++ iterator. The use of iterators is a common design pattern in object-oriented programming that hides the way the collection/container is implemented internally. Hence a set of atoms could be implemented internally as an array, a linked list, a hash table, or any similar data structure, but its behavior to the programmer is independent of the actual implementation. An iterator can be thought of as a current position indicator.

In C++, OEChem iterators make use of C++'s template mechanism. The use of templates allows the functionality of an iterator to be specified independently of the type of the collection being iterated over. An iterator over atoms is defined as type ``OEIter<OEAtomBase>'' and an iterator over bonds has type ``OEIter<OEBondBase>''.

In the Python wrapper, these instantiations are replaced with method calls on the OEMolBase. To get an iterator over the atoms in an OEMolBase ``mol'', one would use mol.GetAtomIter() and likewise a call to mol.GetBondIter() would return a reference to an iterator over the bonds of the molecule. The generator methods described in the previous section make use of these iterator methods, but simplify it for simple looping over the atoms and bonds.

If a programmer wants to use iterators directly in Python, the following table describes the translation from C++ OEIterBase operators and methods to the Python wrapper methods.

  C++ Python
Creation OEIter<OEAtomBase> i = mol.GetAtoms(); i = mol.GetAtomIter()
Increment ++i; i.Next()
Decrement -i; i.Prev()
Increment by n i += n; i.Next(n)
Decrement by n i -= n; i.Prev(n)
Go to first i.ToFirst(); i.ToFirst()
Go to last i.ToLast(); i.ToLast()
De-reference (access the object operator -> i.Target()
pointed to, i.e. OEAtomBase)    
Validity operator bool i.IsValid()

The next example show how to use the an OEAtomBase iterator directly to loop over the atoms in a molecule in reverse order and print their atomic numbers.

#!/usr/bin/env python
# ch6-5.py
from openeye.oechem import *

mol = OEGraphMol()
OEParseSmiles(mol, "n1ccccc1")

iter = mol.GetAtomIter()
iter.ToLast()
while iter.IsValid():
    print iter.Target().GetAtomicNum()
    iter.Prev()