Problem with iterators and inheritance

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Yves

    #1

    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__=='__ma in__':
    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
  • Scott David Daniels

    #2
    Re: Problem with iterators and inheritance

    Yves wrote:
    (in surprise because C's __init__ doesn't over-ride next)[color=blue]
    > 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()[/color]

    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
    scott.daniels@a cm.org

    Comment

    Working...