5

Just starting out Python, i'm a fan of Derek Banas and have been following a tutorial and I'm stuck with a bit of code.

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 say {} 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", "Seb")
print(spot.tostring())

And i'm receiving the following error:

Traceback (most recent call last):
 File "G:/JetBrains/PyCharm Community Edition 4.5.4/PyCharm Projects/Testing 123/testing objects.py", line 87, in <module>
 print(spot.tostring())
 File "G:/JetBrains/PyCharm Community Edition 4.5.4/PyCharm Projects/Testing 123/testing objects.py", line 73, in tostring
 return "{} is {} cm tall and {} kilograms and say {} His owner is {}".format(self.__name,
AttributeError: 'Dog' object has no attribute '_Dog__name'

As I've previously transferred from programming with vb, the indentation for the format of the 'tostring' method baffles me a little bit. I even tried putting it all into one line and it still doesn't recognize the inherited attribute '__name' from the class Animal.

Help would be appreciated.

Edit:

It might be worth mentioning that i'm using Pycharm to write all this in.

Also here's the Animal class

class Animal:
 __name = ""
 __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
 def set_name(self, name):
 self.__name = name
 def set_height(self, height):
 self.__height = height
 def set_weight(self, weight):
 self.__weight = weight
 def set_sound(self, sound):
 self.__sound = sound
 def get_name(self):
 return self.__name
 def get_height(self):
 return self.__height
 def get_weight(self):
 return 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 say {}".format(self.__name,
 self.__height,
 self.__weight,
 self.__sound)
asked Oct 14, 2015 at 16:54
3
  • 1
    Since name is set in the super, we would probably need to see the Animal code. As an aside, creating a tostring() method is rather un-pythonic, as you would want to look at overriding the __str__ and __repr__ magic methods. Commented Oct 14, 2015 at 16:57
  • That's true, wasn't sure if it was necessary if what I said was that the attribute it was trying to find already exists in the super its inheriting, but I'll add the Animal class code to the original post. Commented Oct 14, 2015 at 17:01
  • 1
    If you've got this from a tutorial, you should get another one straight away. This is totally un-Pythonic code. Commented Oct 14, 2015 at 17:04

3 Answers 3

5

Your Animal class is using Name Mangling. From documentation -

Since there is a valid use-case for class-private members (namely to avoid name clashes of names with names defined by subclasses), there is limited support for such a mechanism, called name mangling. Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped.

(Emphasis mine)

Hence , after your Animal class got defined any name such as __name would have changed to _Animal__name , etc. You would also need to access them alike that in your Dog class.

But I don't think you actually need to use Name Mangling , you should avoid using the two leading underscores, if you didn't mean for Name Mangling to happen.

answered Oct 14, 2015 at 17:00
Sign up to request clarification or add additional context in comments.

2 Comments

In short: use a single trailing underscore, not double.
Thanks, this seems to have worked. Is name mangling something that has been introduced within the last year? I ask this because inside the tutorial I was looking at they did not have any problems with using 2 underscores for their attributes.
2

Change your function code

from

def toString(self):
 return "{} is {} cm tall and {} kilograms and say {} and the owner is {}".format(
 self.__name,
 self.__height,
 self.__weight,
 self.__sound,
 self.__owner)

to

def toString(self):
 return "{} is {} cm tall and {} kilograms and say {} and the owner is {}".format(
 self.get_name(),
 self.get_height(),
 self.get_weight(),
 self.get_sound(),
 self.get_owner())
Sunil Sharma
2,6891 gold badge27 silver badges36 bronze badges
answered Sep 5, 2018 at 15:17

1 Comment

Hi @Simon Neubauer, could you please add some more explanation to your answer?
0

The child class itself doesn't have the attribute, use this instead.

return super(Dog, self).toString() + "His owner is {}".format(self.__owner)
answered Apr 27, 2016 at 17:08

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.