471,091 Members | 1,562 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,091 software developers and data experts.

Problem with iterators and inheritance

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
May 8 '06 #1
1 1394
Yves wrote:
(in surprise because C's __init__ doesn't over-ride next)
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 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()


The answer is to understand the following code:
class Xyz(object):
def __init__(self): self.x = 23
def x(self): return 42
print Xyz().x

New-style classes control object attribute lookups,
and messages go to the class first (ignoring the instance
dictionary). That is also how "properties" work, which
(if you think about it right) could not otherwise survive
the first assignment of the property.

--Scott David Daniels
sc***********@acm.org
May 8 '06 #2

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

45 posts views Thread by Joh | last post: by
8 posts views Thread by babak | last post: by
15 posts views Thread by fungus | last post: by
19 posts views Thread by fungus | last post: by
6 posts views Thread by gexarchakos | last post: by
18 posts views Thread by desktop | last post: by
3 posts views Thread by Jess | last post: by
4 posts views Thread by conrad | last post: by
11 posts views Thread by Juha Nieminen | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.