Error: "x instance has no attribute y" when trying to inherit from class

11,315

Solution 1

You overwrite the original __init__, which is then never called and doesn't initialize the members. You must call the parent's __init__ separately, usually with this snippet:

def __init__(self):
    super(Score, self).__init__()

See the docs for super() for details. However, super() only works for so-called new-style classes. You must therefore either change the definition of Play to inherit from object:

class Play(object)

or you call the parent's method directly:

def __init__(self):
    Play.__init__(self)

Solution 2

When you inherit from the class Play, you automatically get the attributes that you've created in the definition of Play, but you don't get the attributes that you've created in Play.__init__. You have to explicitly call it like so:

class Score(Play):
    def __init__(self):
        Play.__init__(self)
        self.initialScore = 0

See Boldewyn's suggestion for using super to do this; but IMO you should probably get used to the basic way inheritance works before fiddling with super.

To further clarify, if you don't override __init__ as you have in this case, then it's inherited and called automatically.

Solution 3

You forgot to initialize the superclass.

class Score(Play):
  def __init__(self):
    super(Score, self).__init__()
    self.initialScore = 0
Share:
11,315
Trufa
Author by

Trufa

Existing code exerts a powerful influence. Its very presence argues that it is both correct and necessary.

Updated on June 05, 2022

Comments

  • Trufa
    Trufa about 2 years

    I can't really understand what I'm doing wrong, since when I try it in "small scale" and it is working there.

    I have a class named Play()

    I goes like this:

    class Play():
        def __init__(self):
            file = open("/home/trufa/Desktop/test", "r")
            self.word = random.choice(file.readlines()).rstrip()
            self.errAllowed = 7
            self.errMade = 0
            self.errList = []
            self.cheatsAllowed = 2##chetas not incrementing
            self.cheatsMade =0
            self.wordList = ["*"]*len(self.word) ##this one is the one I want to have available in another class
    

    ...

    Then I have another class called Score()

    class Score(Play):
        def __init__(self):
            self.initialScore = 0
    
        def letterGuess(self):
            self.initialScore += 1
            return self.errList
    

    ...

    I instantiated both:

    game = Play()
    points = Score()
    

    And if I do:

    print points.letterGuess()
    

    It gives me an error:

    Traceback (most recent call last):
      File "/home/trufa/workspace/hangpy/src/v2.py", line 188, in <module>
        startGame()
      File "/home/trufa/workspace/hangpy/src/v2.py", line 134, in startGame
        print points.letterGuess()
      File "/home/trufa/workspace/hangpy/src/v2.py", line 79, in letterGuess
        return self.errList
    AttributeError: Score instance has no attribute 'errList'
    

    I don't understand why since I can do this without any trouble:

    class One():
        def __init__(self):
            self.list= [1,2]
    
    class Two(One):
        def meth(self):
            return self.list
    
    uan = One()
    tu = Two()
    
    print uan.list 
    print tu.meth() ## Both output [1,2]
    

    I'm very new to OOP so I could be doing all kinds of silly mistakes but I can't figure out where!

    I think I have posted all the relevant code, but I you think the error might be elsewhere, I can provide it.

    As I said I'm very new, so this might have nothing to do with inheritance I just think it called that when you get "something" from within another class (you must be shouting at the screen by now)

  • Trufa
    Trufa about 13 years
    Thank you very much, I'm sure this is obvious, but you have to learn it at some point I guess :) +1 for first and correct answer!
  • senderle
    senderle about 13 years
    To further clarify, you must inherit from object in 2.x. In 3.x, old-style classes go away, so inheriting from object is unnecessary.
  • Boldewyn
    Boldewyn about 13 years
    @senderle: True, thanks. I should start to respect 3 more and not take it as given, that 2.x is used.
  • Trufa
    Trufa about 13 years
    I haven't yet understood how to use super(), wasn't this what you suggested.
  • senderle
    senderle about 13 years
    @Bolderwyn, I'm struggling to do that myself -- hence the comment. :)
  • Boldewyn
    Boldewyn about 13 years
    @Trufa: no, I made the same mistake, when I first started to use it. The first argument to super() is the own class, in the pastie example, Two. Think of it this way: super() returns the super-class of its first argument.
  • Boldewyn
    Boldewyn about 13 years
    By the way, in this way you can also call methods of super-super-classes all the way up the inheritance chain. If One inherits from Zero and isinstance(self, Two), super(One, self).__init__ is the method of the class Zero.
  • Trufa
    Trufa about 13 years
    @Boldewyn: No I'm even more confused! :) you say like this? def __init__(self): super(Two, self).__init__() (I say that what you suggest is in the docs, but I'm not figuring out somthing)
  • senderle
    senderle about 13 years
    @Trufa, I wrote a long comment that wound up reproducing what Bolderwyn has already said. So I'll just add that this is why I suggested getting used to inheritance before trying to use super. :)
  • Boldewyn
    Boldewyn about 13 years
    Read this just the other minute via delicious: rhettinger.wordpress.com/2011/05/26/super-considered-super
  • Trufa
    Trufa about 13 years
    @senderle: I am actually using you method, but just trying to understand that for later. Thank for all the help!
  • Trufa
    Trufa about 13 years
    @Boldewyn: hmm ok but its not working that, way. I'm confused... I'll take another shot at it but I'll have @senderle 's advice in mind.