0

With a simple pair of classes, I cannot get super working:

class A(object):
    q = 'foo'
class B(A):
    q = 'bar'
    def __init__(self):
        self.a = super(A, self).q
a = B()

errors like so:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-210-802575054d17> in <module>()
      5     def __init__(self):
      6         self.a = super(A, self).q
----> 7 a = B()

<ipython-input-210-802575054d17> in __init__(self)
      4     q = 'bar'
      5     def __init__(self):
----> 6         self.a = super(A, self).q
      7 a = B()

AttributeError: 'super' object has no attribute 'q'

I've looked through similar problems on stack exchange, read documentation and articles, and by all accounts this should be working. What obvious thing am I missing?

EDIT: The answer is that I'm referencing the wrong class, and fixing it fixes the example, but not my real code which is below:

class D(object):
    pwd = ['~/']
    def __init__(self,*args):
        if len(args) == 1:
            self.cd(args[0])
        else:
            return
    def __str__(self):
        if len(self.pwd) == 1:
            return self.pwd[0]
        else:
            return ''.join(self.pwd)
    def __add__(self,other):
        if type(other) is str:
            return str(self) + other
        elif type(other) is list:
            return pwd + other
    def cd(self, directory):
        #import pdb; pdb.set_trace()
        reset = False
        if directory[0] is '~':
            reset = True
        if directory[0] is '/':
            reset = True
            directory = directory[1:]
        if directory[-1] is '/':
            directory = directory[:-1]
        directory = [folder+'/' for folder in directory.split('/')]
        rverse = directory.count('../')
        if rverse > 0 and type(directory) is list:
            end = False
            for folder in directory:
                if folder == '../' and end:
                    raise Exception('improperly placed ".."')
                if folder != '../':
                    end = True
        if reset:
            self.pwd = directory
        else:
            self.pwd = self.pwd + directory
        print self
class Dirchanger(D):
    def __init__(self,client,*args):
        if len(args) == 1:
            self.cd(args[0])
    def cd(self,directory):
        super(D, self).cd(directory)

Obviously, that code is incomplete, but it should work based on the answer.

BFH
  • 99
  • 7
  • 1
    That's because it probably should be `super(B, self).q`, and _not_ `super(A, self).q` – Stefan van den Akker Jun 02 '14 at 17:53
  • If the only thing `Dirchanger.cd` does is call `D.cd`, with the same argument, you don't need to define it. If you try to call `Dirchanger().cd(somedir)`, the attribute lookup algorithm will find `D.cd` automatically. – chepner Jun 02 '14 at 18:21
  • My actual problem is that I didn't change the code properly. I guess I'll keep my private code in there as a monument. The reason it looks that way is that it's incomplete. I want to write in some extra error handling. – BFH Jun 02 '14 at 18:24

1 Answers1

4

You are using the wrong search target (the first argument); use super(B, self) instead:

def __init__(self):
    self.a = super(B, self).q

The first argument gives super() a starting point; it means look through the MRO, starting at the next class past the one I gave you, where the MRO is the method resolution order of the second argument (type(self).__mro__).

By telling super() to start looking past A, you effectively told super() to start the search too far down the MRO. object is next, and that type doesn't have a q attribute:

>>> B.__mro__
(<class '__main__.B'>, <class '__main__.A'>, <type 'object'>)

Your real code has the exact same issue:

class Dirchanger(D):
    def __init__(self,client,*args):
        if len(args) == 1:
            self.cd(args[0])
    def cd(self,directory):
        super(D, self).cd(directory)

You are starting the MRO search at D, not Dirchanger here.

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