0

I've been having this issue with this code, and I'm not sure why I'm still getting this TypeError here. I have the following Animal class, which is the base class for the Dog class defined below it. I want to create a Dog object which inherits from this Animal class.

Here's the Animal class:

class Animal(object):
    __name = None
    __height = None
    __weight = None
    __sound = None

    def __init__(self, name, height, weight, sound):
        self.__name = name
        self.__height = height
        self.__weight = weight
        self.__sound = sound

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

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

    def set_weight(self, height):
        self.__height = height

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

    def get_name(self):
        return self.__name

    def get_height(self):
        return str(self.__height)

    def get_weight(self):
        return str(self.__weight)

    def get_sound(self):
        return self.__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)

And then I have the following Dog class which inherits from the above Animal class:

class Dog(Animal):
    __owner = None

    def __init__(self, name, height, weight, sound, owner):
        self.__owner = owner
        super(Dog, self).__init__(self, 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)

When I try to create a Dog object with the following code:

spot = Dog('Spot', 22, 11, 'Bark', 'John')

I get the following TypeError:

TypeError: __init__() takes exactly 5 arguments (6 given)

Does anyone know why I'm getting this error? I'm not really understanding what's going on here.

Thanks in advance!

Edit: After taking out the self from the superclass, I now am getting an AttributeError: 'Dog' object has no attribute '_Dog__name' when I try the following code:

print(spot.toString())
Asad
  • 3
  • 1
  • 4
  • The interpreter is right! – styvane May 31 '16 at 16:11
  • 1
    Just drop first `self` from superclass, it's implicitly passed via `super` call. – Łukasz Rogalski May 31 '16 at 16:11
  • 2
    This isn't Java. You shouldn't be writing a dozen getters and setters, or using double-underscore names unnecessarily, or declaring instance attributes at class level, or calling your string conversion method `toString`. – user2357112 May 31 '16 at 16:12
  • Thanks for the heads up. This is actually code from an online tutorial, and I'll keep what you said in mind. – Asad May 31 '16 at 16:18
  • @AsadMehdi the whole point of using two underscores is so that sources outside the class cannot access them (Including your `Dog` subclass) you will need to use the `self.get_name()` instead of `self.__name` from your `Dog` class (otherwise what is the point of the getters anyway?) – Tadhg McDonald-Jensen May 31 '16 at 16:30
  • On top of the fact that you shouldn't be using getters, setters and "private" variables, instead of `toString`, you should be using `__str__`: http://stackoverflow.com/questions/1436703/difference-between-str-and-repr-in-python – Random Davis May 31 '16 at 17:30

1 Answers1

2

Problem lays in __init__ method of superclass. super() call implicitly passes self as first argument. Simply use:

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

Explicit self is necessary only when you refer to superclass by it's name.

def __init__(self, name, height, weight, sound, owner):
    self.__owner = owner
    Animal.__init__(self, name, height, weight, sound)
Łukasz Rogalski
  • 22,092
  • 8
  • 59
  • 93
  • Thanks for the quick reply. However, I'm now getting the following error: `AttributeError: 'Dog' object has no attribute '_Dog__name'` I actually tried to do what you suggested before, but reverted back when I started getting this error. Do you know what's wrong here? I should also mention that I am doing this after constructing the Dog object: `print(spot.toString())`. I'll add this in my original post. – Asad May 31 '16 at 16:17
  • 1
    You have just experienced [name mangling mechanism](http://stackoverflow.com/questions/1301346/the-meaning-of-a-single-and-a-double-underscore-before-an-object-name-in-python) – Łukasz Rogalski May 31 '16 at 16:21
  • @AsadMehdi If answer was helpful, please [accept it](http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work). – Łukasz Rogalski May 31 '16 at 17:12