Python class not inheriting properties from its parent

I am new to the Python programming language, and I am working my way through a tutorial on object-oriented programming in Python.  The purpose of the lesson is to learn the important topic of inheritance of classes.  (Here's a shoutout to Derek, who is hosting this excellent tutorial: https://www.youtube.com/watch?v=N4mEzFDjqtA.)

Having created a class called Animal, I then create a new class called Dog, based on Animal.  The program is giving me the error that the Dog class does not recognize the variables inherited from the super class Animal.  Following is my code, and this is my error: "AttributeError: 'Dog' object has no attribute '_Dog__Name'", which comes within Dog.toString() (lines 67-68).   My assumption is that the class definition, "class Dog(Animal):", defines Dog as inheriting attributes from Animal, and Derek's code worked when ran as written here.  Is there something I'm missing?

import random
import sys
import os

#Object-oriented programming
class Animal:
    __Name = None
    __Height = 0
    __Weight = 0
    __Sound = 0

    def set_name(self, name):
        self.__Name = name

    def get_name(self):
        return self.__Name

    def set_height(self, height):
        self.__Height = height

    def get_height(self):
        return self.__Height

    def set_weight(self, weight):
        self.__Weight = weight

    def get_weight(self):
        return self.__Weight

    def set_sound(self, sound):
        self.__Sound = sound

    def get_sound(self):
        return self.__Sound

    def __init__(self, name, height, weight, sound):
        self.__Name = name
        self.__Height = height
        self.__Weight = weight
        self.__Sound = sound

    def get_type(self):
        print ("Animal")

    def toString(self):
        return "{} is {} cm tall and {} kilograms and says {}".format(self.__Name, self.__Height, self.__Weight, self.__Sound)

cat = Animal("whiskers", 33, 10, 'Meow')

print(cat.toString())

class Dog(Animal):
    __Owner = ""

    def __init__(self, name, height, weight, sound, owner):
        self.__Owner = owner
        super(Dog, self).__init__(name, height, weight, sound)

    def set_owner(self, owner):
        self.__Owner = owner

    def get_owner(self):
        return self.__Owner

    def get_type(self):
        print("Dog")
    def toString(self):
        return "{} is {} cm tall and {} kilograms and says {}.  His owner is {}".format(self.__Name, self.__Height, self.__Weight, self.__Sound, self.__Owner)
    def multiple_sounds(self, how_many=None):
        if (how_many is None):
            print(self.get_sound())
        else:
            print(self.get_sound() * how_many)



spot = Dog("Spot", 53, 27, "Ruff", "Derek")
print(spot.toString)

Open in new window

PeterFrbWeb development, Java scripting, Python TrainingAsked:
Who is Participating?
 
Cyclops3590Commented:
couple issues I see

1) when declaring Animal class, to be consistent across python version it should be "class Animal(object):".  object is the base class type and in some versions is inferred, but others is not.  so best to be explicit.  That fixes the exception thrown in 2.7

2) print(spot.toString) should be print(spot.toString()) since toString is a function otherwise you're passing the actual function as a variable to print instead of the text that you want to retrieve from toString.

Also, why you can't use self.__Name in a subclass is because it's a private variable declared in Animal class.  Look up data mangling and private variables in python docs.  It'll explain it better than I can.  Basically, if you wanted to use it in Dog, you need to use self._Animal__Name instead of self.__Name.  Due to data mangling, using self.__Name in Dog is like referencing self._Dog__Name which clearly isn't what you want
0
 
NorieVBA ExpertCommented:
Which version of Python are you using?

When I run the code In Python3.6.1 I don't get any 'errors' but I do get this output.

whiskers is 33 cm tall and 10 kilograms and says Meow
<bound method Dog.toString of <Dog object at 0x7ff47d33ccc0>>

When I run it in Python2.7.14 I get this error.

Traceback (most recent call last):
  File "C:/Test/PythonExamples/EEDoggyEx.py", line 77, in <module>
    spot = Dog("Spot", 53, 27, "Ruff", "Derek")
  File "C:/Test/PythonExamples/EEDoggyEx.py", line 57, in __init__
    super(Dog, self).__init__(name, height, weight, sound)
TypeError: super() argument 1 must be type, not classobj
0
 
PeterFrbWeb development, Java scripting, Python TrainingAuthor Commented:
I use the same version, and that's pretty much what I get also.  The instructor uses a previous version than what I had, and I actually figured out what to do.  I had an epiphany about this: Dog does not have direct access to the variables residing in Animal, as it apparently does in version 3.4 of Python, but it does have access to the properties as defined in Animal.  The answer, therefore, is to use said properties.  My updated code looks as follows:  

    def toString(self):
        return "{} is {} cm tall and {} kilograms and says {}.  His owner is {}".format(self.get_name(), self.get_height(), self.get_weight(), self.get_sound(), self.__Owner)

Open in new window


Why version 3.4 worked and 3.6 does not is anyone's guess, but at least Derek did the due diligence of putting those properties in Animal, which allowed me to make the leap to finding the solution.
0
 
Cyclops3590Commented:
feel free to delete, but I added why things are running the way they are and how to fix them.  if that actually isn't what the asker wants, then it should be deleted.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.