Question: When using list comprehension or the `in` keyword in a for loop context, i.e:

```
for o in X:
    do_something_with(o)

```

or

```
l=[o for o in X]

```

* How does the mechanism behind `in` works?
* Which functions\methods within `X` does it call?
* If `X` can comply to more than one method, what's the precedence?
* How to write an efficient `X`, so that list comprehension will be quick?

Answer: 
The, afaik, complete and correct answer.

`for`, both in for loops and list comprehensions, calls `iter()` on `X`. `iter()` will return an iterable if `X` either has an `__iter__` method or a `__getitem__` method. If it implements both, `__iter__` is used. If it has neither you get `TypeError: 'Nothing' object is not iterable`.

This implements a `__getitem__`:

```
class GetItem(object):
    def __init__(self, data):
        self.data = data

    def __getitem__(self, x):
        return self.data[x]

```

Usage:

```
>>> data = range(10)
>>> print [x*x for x in GetItem(data)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

```

This is an example of implementing `__iter__`:

```
class TheIterator(object):
    def __init__(self, data):
        self.data = data
        self.index = -1

    # Note: In  Python 3 this is called __next__
    def next(self):
        self.index += 1
        try:
            return self.data[self.index]
        except IndexError:
            raise StopIteration

    def __iter__(self):
        return self

class Iter(object):
    def __init__(self, data):
        self.data = data

    def __iter__(self):
        return TheIterator(data)

```

Usage:

```
>>> data = range(10)
>>> print [x*x for x in Iter(data)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

```

As you see you need both to implement an iterator, and `__iter__` that returns the iterator.

You can combine them:

```
class CombinedIter(object):
    def __init__(self, data):
        self.data = data

    def __iter__(self):
        self.index = -1
        return self

    def next(self):
        self.index += 1
        try:
            return self.data[self.index]
        except IndexError:
            raise StopIteration

```

Usage:

```
>>> well, you get it, it's all the same...

```

But then you can only have one iterator going at once.
OK, in this case you could just do this:

```
class CheatIter(object):
    def __init__(self, data):
        self.data = data

    def __iter__(self):
        return iter(self.data)

```

But that's cheating because you are just reusing the `__iter__` method of `list`.
An easier way is to use yield, and make `__iter__` into a generator:

```
class Generator(object):
    def __init__(self, data):
        self.data = data

    def __iter__(self):
        for x in self.data:
            yield x

```

**This last is the way I would recommend. Easy and efficient.**
Answering question's comments I can say that reading source is not the best idea in this case. The code that is responsible for execution of compiled code ([ceval.c](http://svn.python.org/view/python/trunk/Python/ceval.c?view=markup)) does not seem to be very verbose for a person that sees Python sources for the first time. Here is the snippet that represents iteration in for loops:

```
   TARGET(FOR_ITER)
        /* before: [iter]; after: [iter, iter()] *or* [] */
        v = TOP();

        /*
          Here tp_iternext corresponds to next() in Python
        */
        x = (*v->ob_type->tp_iternext)(v); 
        if (x != NULL) {
            PUSH(x);
            PREDICT(STORE_FAST);
            PREDICT(UNPACK_SEQUENCE);
            DISPATCH();
        }
        if (PyErr_Occurred()) {
            if (!PyErr_ExceptionMatches(
                            PyExc_StopIteration))
                break;
            PyErr_Clear();
        }
        /* iterator ended normally */
        x = v = POP();
        Py_DECREF(v);
        JUMPBY(oparg);
        DISPATCH();

```

To find what actually happens here you need to dive into bunch of other files which verbosity is not much better. Thus I think that in such cases documentation and sites like SO are the first place to go while the source should be checked only for uncovered implementation details.