Hi!

I was fiddling around a bit with iterators and I came across some

strange behaviour. I have the following simple code:

--

class A(object):

def __init__(self, n):

self.n = n

def __iter__(self):

return self

def next(self):

if self.n > 0:

self.n -= 1

return "A: %d" % self.n

else:

raise StopIteration()

class B(A):

def __init__(self, n):

super(B,self).__init__(n)

def __iter__(self):

return self

def next(self):

if self.n > 0:

self.n -= 1

return "B: %d" % self.n

else:

raise StopIteration()

class C(A):

def __init__(self, n):

super(C,self).__init__(n)

self.next = self.mynext

def __iter__(self):

return self

def mynext(self):

if self.n > 0:

self.n -= 1

return "C: %d" % self.n

else:

raise StopIteration()

if __name__=='__main__':

a = A(2)

b = B(2)

c = C(2)

for k in [a,b,c]:

# Iterate over the object

for i in k:

print i

print "="*50

--

The output I expected was

A: 1

A: 0

==================================================

B: 1

B: 0

==================================================

C: 1

C: 0

==================================================

but strangely enough I ended up with

A: 1

A: 0

==================================================

B: 1

B: 0

==================================================

A: 1

A: 0

==================================================

Or in other words, it appears that Python does not use 'mynext' when

iterating over an object of class C. When I call c.next() directly

though, it does execute the code from the 'mynext' method. In my

understanding, iterating over a list, simply consists of repeatedly

calling the next() function until a StopIteration is raised, so there

should not really be any difference.

Another thing I noticed is that if I do not let A inherit from 'object'

(removing the calls to super(..) and adding appropriate initalization of

self.n), the result is as expected.

I am completely puzzled, so if anybody could shed some light on this,

I'd appreciate this.

YVES