1

Consider the following classes, running python2.7:

class S(object):
  def __init__(self):
    print 'Si'
    self.reset()

  def reset(self):
    print 'Sr'
    self.a=0

class U1(S):
  def reset(self):
    print 'U1r'
    self.b=0
    super(S,self).reset()

The desired functionality is that

  1. creating an instance of the base class calls its reset method;
  2. creating an instance of the derived class calls its reset method, and also invokes the base class's reset method.

I get (1):

>>> print S().a
Si
Sr
0

but not (2):

>>> print U1().b
Si
U1r
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "tt.py", line 4, in __init__
    self.reset()
  File "tt.py", line 14, in reset
    super(S,self).reset()
AttributeError: 'super' object has no attribute 'reset'

What's the cleanest way to get what I want? I presume the error has something to do with the order in which class membership is getting constructed, but I can't figure it out from the documentation. . .

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
HST
  • 67
  • 5

2 Answers2

2

You should be calling super(U1, self).reset() in U1.reset(). When you use super, you should always pass the name of the current class as the first argument, not the name of the parent class. As stated in the docs:

super(type[, object-or-type])

Return a proxy object that delegates method calls to a parent or sibling class of type

super will look up the method on the parent or sibling of the type you provide. When you provide the parent class, it will try to find implementations of reset on parents/siblings of the parent, which will fail.

dano
  • 91,354
  • 19
  • 222
  • 219
  • D'oh. Thanks. I had somehow been looking at too many examples, and gotten the idea that the purpose of the extra argument was to distinguish which superclass I wanted, if there were several. And indeed, as the answers to the duplicate identified above make clear, you can do that, by looking at the __mro__ and naming the class before the one you want (which is why 'parent' isn't really right ...) – HST Oct 02 '14 at 17:16
1

Should be:

super(U1, self).reset()

In my head, I read "super(U1,..." as "parent of U1" to keep it straight.

Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
Adam Hughes
  • 14,601
  • 12
  • 83
  • 122
  • Except in the simple case, 'parent' is misleading, as the answers to the duplicate pointer https://stackoverflow.com/questions/24000419/i-cant-get-super-to-work-in-python-2-7 explain, or see my comment above – HST Oct 02 '14 at 17:22
  • Ah, thanks I would have never know that. – Adam Hughes Oct 02 '14 at 17:27