[Tutor] __getitem__

Kent Johnson kent37 at tds.net
Tue Jan 17 12:28:12 CET 2006


Alan Gauld wrote:
>>map calls, list comprehension, etc.  For loops, etc.
>>work by indexing a  sequences from zero to a higher
>>index until out-of-bounds is reached.  
> 
> 
> What makes you think that?
> So far as I know for loops work by calling next on 
> an iterator until nothing gets returned, no indexes 
> involved.(At least not in the for loop) But they could 
> just as well work by calling the len() function and 
> iterating that number of times. And len() could be 
> stored as part of the data structure ala Pascal arrays.

Hmm. From the language ref description of 'for':
"The expression list is evaluated once; it should yield an iterable object."

which begs the question of, what is an iterable object? The iterator 
protocol was introduced in Python 2.2; the "What's New" document give a 
good description of the old and new methods of iterating. Prior to 
Python 2.2, the _only_ way to make an object iterable was to give in a 
__getitem__() method. With Python 2.2 you can alternatively define 
__iter__().
http://www.python.org/doc/2.2.3/whatsnew/node4.html

 From the language ref description of __getitem__():
"Note: for loops expect that an IndexError will be raised for illegal 
indexes to allow proper detection of the end of the sequence."

In fact a class that just defines __getitem__() can be iterated in a for 
loop:

  >>> class stepper:
  ...   def __getitem__(self, i):
  ...     if i < 5: return i
  ...     raise IndexError
  ...
  >>> for i in stepper(): print i
  ...
0
1
2
3
4

> 
> The point being that it is dangerous to assume how 
> a language feature works internally, it can change from 
> version to version.

Dangerous to assume, maybe, but special methods are there to be used, 
and the usage is generally well understood if not always well documented.
> 
> In this case the iterator solution means that the for 
> loop can work on any iterable entity - like files for 
> instance.

Yes, and for backward compatibility it also works on anything 
implementing __getitem__(). In fact strings have no __iter__() method, 
they use __getitem__():
  >>> ''.__iter__
Traceback (most recent call last):
   File "<stdin>", line 1, in ?
AttributeError: 'str' object has no attribute '__iter__'
  >>> ''.__getitem__
<method-wrapper object at 0x00A32E50>

> 
> 
>>But why does this work?
>>
>>
>>>>>class stepper:
>>
>>...     def __getitem__(self, i):
>>...         return self.data[i]
>>...
>>
>>>>>'p' in X
>>
>>True
>>
>>What does 'in' have to do with indexing?
> 
> 
> Nothing unless its implementation uses a while loop
> and index, but thats unlikely.

But that is pretty close to what actually happens, according to the 
language ref docs for 'in' (see my previous post).

Kent



More information about the Tutor mailing list