Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

__getitem__ overloading in python

I am trying to understand the operator overloading in python and I have written a small programs which overloads __getitem__() method and calls a for loop:

class Ovl:
    data = [1,2,3,4,5]
    def __getitem__(self, index):
        return "Hiii"

x=Ovl()

for item in x:
    print item

This program goes in to a infinite for loop printing "Hiii". I would like to know the reason behind it.

like image 364
gthm Avatar asked Oct 28 '14 14:10

gthm


2 Answers

According to the object.__getitem__ NOTE,

NOTE: for loops expect that an IndexError will be raised for illegal indexes to allow proper detection of the end of the sequence.

>>> class Ovl:
...     data = [1,2,3,4,5]
...     def __getitem__(self, index):
...         if index >= 5:
...             raise IndexError('End')
...         return "Hiii"
...
>>> x=Ovl()
>>>
>>> for item in x:
...     print item
...
Hiii
Hiii
Hiii
Hiii
Hiii
like image 176
falsetru Avatar answered Sep 28 '22 07:09

falsetru


The overloading of __getitem__ actually lets you do something like this:

>>> x = Ovl()
>>> x[6]
'Hi'
>>> x[8]
'Hi'

If you want to implement iterating over your class with for, you need to overload __iter__ method (see here: How to implement __iter__(self) for a container object (Python)).

The reason for your loop running infinite thing is that the default implementation of __iter__ apparently calls __getitem__ internally. Actually, your for loop calls __getitem__(0), __getitem__(1), __getitem__(2), ... sequentially, so it seems to run infinite.

If you would modify your __getitem__ method:

def __getitem__(self, index):
    return index, "Hi"

You can see exactly what's happening:

>>> x = Ovl()
>>> for item in x:
    print item 

(0, 'Hi')
(1, 'Hi')
(2, 'Hi')
(3, 'Hi')
(4, 'Hi')
(5, 'Hi')
(6, 'Hi')
...
like image 24
michailgames Avatar answered Sep 28 '22 08:09

michailgames