3

I'm just starting out with Python, but I cannot figure out why I'm having a problem with such simple class inheritance, and despite the common use of the tutorial I've been following, I haven't seen anyone else on Stack Overflow encountering this issue. Here's the code (don't worry, nothing too complicated):

import random import sys import os 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 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()) bird = Animal ('Flutie', 33, 10, 'tweet') print(bird.toString()) class Dog(Animal): def __init__(self, name, height, weight, sound): super(Dog, self).__init__(name, height, weight, sound) def toString(self): return "{} is {} cm tall and {} kilograms and says {}".format(self.__name, self.__height, self.__weight, self.__sound) spot = Dog ('Spot', 53, 27, "Woof") print(spot.toString()) 

...And here's the output:

Whiskers is 33 cm tall and 10 kilograms and says meow Flutie is 33 cm tall and 10 kilograms and says tweet Traceback (most recent call last): File "C:/.../animal_test.py", line 72, in <module> print(spot.toString()) File "C:/.../animal_test.py", line 65, in toString return "{} is {} cm tall and {} kilograms and says {}".format(self.__name, AttributeError: 'Dog' object has no attribute '_Dog__name' 
10
  • 4
    Double underscores in attribute names have a special meaning in python: stackoverflow.com/questions/1301346/… Commented Jun 11, 2017 at 0:46
  • 3
    Aside from the name mangling issues, setting __name = '' etc. at the class level probably doesn't do what you think, serves no purpose here, and is likely to lead to problems later. Commented Jun 11, 2017 at 0:48
  • 2
    Python != Java. Stop writing double-underscore name-mangled attributes unless that is what you want, that, you are trying to create class-local references, which it certainly isn't what you want given that you are trying to access the attributes in a subclass. Stop writing attributes at the class level that you are only going to shadow at the instance level, i.e. __name = "" This almost certainly isn't doing what you think it is doing. Don't write a toString method, use __str__. Commented Jun 11, 2017 at 1:09
  • 1
    Out of curiosity, what tutorial are you following? Commented Jun 11, 2017 at 1:12
  • 2
    @PlatypusEgg I'm highly skeptical of that tutorial. Just giving it a quick look, the person has all the classic signs of someone teaching you Java in Python. They use parentheses around conditional statements: if (something is something): . They use errant semi-colons ending lines. And the example of the class definition is totally non-pythonic because of the things I mentioned above. He also teaches you to write getters and setters, which is not the you do encapsulation in Python. They are probably coming from either Java/C++ . Get a better Python tutorial if you want to learn Python. Commented Jun 11, 2017 at 5:34

1 Answer 1

4

The double underscores represents name mangling.

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

Literally translates to this when being interpreted:

class Animal: def __init__(self, name, height, weight, sound): self._Animal__name = name self._Animal__height = height self._Animal__weight = weight self._Animal__sound = sound 

It doesn’t matter where it’s called, or who called the __init__, the prefix _Animal will take place because it’s physically located under the Animal class.

But when you used the attributes here, as it’s physically located under the Dog class, the got name mangled to this:

class Dog(Animal): def __init__(self, name, height, weight, sound): super(Dog, self).__init__(name, height, weight, sound) def toString(self): return "{} is {} cm tall and {} kilograms and says {}".format(self._Dog__name, self._Dog__height, self._Dog__weight, self._Dog__sound) 

Which the Dog object definitely doesn’t have an attribute named self._Dog__name, instead it has the attribute self._Animal__name.

Sign up to request clarification or add additional context in comments.

6 Comments

Interesting. Removing the double-underscores from all the attributes made the code work, so thank you. I think I understand how the name-mangling caused the problem. I guess my only question now is why it also worked for the highly-credible tutorial I was following: youtube.com/watch?v=N4mEzFDjqtA. The class introduction stuff starts at 32 mins. He is using Python version 3.4.2...
That tutorial isn’t particularly a good one...he made the mistake but didn’t explain/catch it in the video. In his actual code, he called the getter functions instead of the underscored attributes. Ie. he did this in his actual code: self.get_name() instead of self.__name() inside the Dog class’s toString string formatting
Here’s his code: newthinktank.com/2014/11/python-programming , scroll down to where the Dog class is defined, note how his toString function differs from the videos’
I intend to keep watching tutorials in order to start to understand general preferences for certain methods, but if there's one you'd highly recommend for a beginner to Python (and non-markup programming in general), I'd love to know it.
I learned python by reading lots of books :D but the official python tutorial is pretty neat docs.python.org/3.6/tutorial , and code academy has a hands-on tutorial codecademy.com/learn/python . For video tutorials, sorry I don’t have any preference...
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.