2

I am experimenting with basic python inheritance with a Dog class that inherits from an Animal class. For some reason, my Dog object is not inheriting name correctly and I keep getting AttributeError: 'Dog' object has no attribute '_Dog__name'. Does anyone know what might be going on? My code is below:

class Animal(object):
    __name = None #signifies lack of a value
    __height = 0
    __weight = 0
    __sound = 0

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


class Dog(Animal):
    def __init__(self, name, height, weight, sound, owner):

        super(Dog, self).__init__(name, height, weight, sound)

        self.__owner = owner
        #self.__name = name this works if I uncomment this line.

    __owner = ""

    def toString(self):
        return "{} belongs to {}".format(self.__name, self.__owner)
        #return 'Sup dawg'

fido = Dog("Spot", 3, 4, "Woof", "John")

print(fido.toString())
2
  • Do not use double-underscore name mangling unless you understand what it is actually for! It is not the same thing as a "private" access modifier. Also, do not use class variables that you only shadow with instance variables. Python != Java Commented Aug 24, 2017 at 22:30
  • Do not use this tutorial. The person who made it clearly not a Python programmer, and is probably someone who writes lot's of Java code. I mean seriously, toString? Commented Aug 24, 2017 at 22:37

1 Answer 1

5

The purpose of __-prefixed attribute names is to mangle them so that subclasses cannot easily access them, to prevent them from accidentally being overridden. The error message shows you how the parent class mangles the name, so you could use that directly:

def toString(self):
    return "{} belongs to {}".format(self._Dog__name, self.__owner)

but you really should just dispense with the prefix and use a regular name. Also, don't define a toString method; use __str__ instead. The class-level initializers are also unnecessary.

class Animal(object):
    def __init__(self, name, height, weight, sound):
        self.name = name
        self.height = height
        self.weight = weight
        self.sound = sound

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

    def __str__(self):
        return "{} belongs to {}".format(self.name, self.owner)

fido = Dog("Spot", 3, 4, "Woof", "John")
print(fido)  # print will convert fido to a string implicitly, using its __str__ method
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.