[Tutor] New Style Classes, __getitem__ and iteration

wesley chun wescpy at gmail.com
Tue May 20 00:09:33 CEST 2008


>  I think it is really magical that, when I define __getitem__ on classic
>  classes, the built-in iterator uses it.
>
>  But, when I make the same class as a new style class, I lose this behavior.
>
>  I didn't realize that something was lost in defining a new style class.
>  Maybe it's something else that I'm missing.


marilyn,

the problem isn't related to you using a new-style class.  if you
ported the classic class directly, it works just fine:

class Circle2(object):
   def __init__(self, data, times):
       """Put the 'data' in a circle that goes around 'times' times."""
       self.data = data
       self.times = times

   def __getitem__(self, i):
       """circle[i] --> Circle.__getitem__(circle, i)."""
       l_self = len(self)
       print 'i, self.times, l_self:', i, self.times, l_self
       if i >= self.times * l_self:
           raise IndexError, \
                 "Error raised: Circle object only goes around %d times"\
                 % self.times
       return self.data[i % l_self]

   def __len__(self):
       return len(self.data)

$ ./circle_question.py
['a', 'a', 'a', 'd', 'd', 'd', 'n', 'n', 'n', 'o', 'o', 'o', 'r', 'r',
'r', 'u', 'u', 'u']

to really start to debug your code, change the call from sorted() to
list(), as in:

circle = Circle2("around", 3)
print list(circle)

the output will change to:

$ ./circle_question.py
['a', 'r', 'o', 'u', 'n', 'd', 'a', 'r', 'o', 'u', 'n', 'd', 'a', 'r',
'o', 'u', 'n', 'd']

when you call sorted() or list() on your object, it attempts to build
a new list consisting of the return values of each getitem() call.
the difference is that with your original class, it doesn't "end"
until the count has surpassed the number of times you want it (3) and
the number of elements total (6), meaning it stops when you go beyond
18.

i put in a tiny print statement in the __getitem__() code in all 3
classes. in the original classic class and my port to new-style
classes, that print statement told me everything i just said above.
the thing that is different about your new-style class is that it
subclasses list.   in your class that derives from list, it did not
execute your __getitem__() method even once.

that clues me in on my belief that the reason why it doesn't work is
because it is *already* a list.  calling list() or sorted() on it
attempts to create a new list, but since the original data structure
is a list, it merely just copies all of its references without using
getitem().

without looking at the source code, i can't confirm this.  can anyone
else "finish the sentence i started?"

hope this partially helps!
-- wesley
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
"Core Python Programming", Prentice Hall, (c)2007,2001
    http://corepython.com

wesley.j.chun :: wescpy-at-gmail.com
python training and technical consulting
cyberweb.consulting : silicon valley, ca
http://cyberwebconsulting.com


More information about the Tutor mailing list