1

I am having hard time understanding this. Let's say we have a snippet of code as such

class Animal:
        def __init__(self, name, food):
                self.name = name
                self.__food = food
        def getFood(self):
                return self.__food

Then we initialize it

>>> animal = {}
>>> animal["dog"] = Animal("rusty", "delicious thing you never know")

Now, while accessing the attributes, It seems to not let me access __food

>>> animal["dog"].name
'rusty'
>>> animal["dog"].__food
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: Animal instance has no attribute '__food'

Why does that fail. As we can clearly see I am using self.__food = food where __ is magic method. So how do I print the __food Magic attribute ?

8
  • 3
    If you want to access __food outside the class body, then don't use leading underscores (the primary purpose of leading underscores is to weakly "hide" variables through name-mangling). You'll find it as _Animal__food Commented Mar 17, 2018 at 19:49
  • @cᴏʟᴅsᴘᴇᴇᴅ , great. That clears the doubt. So _Animal a magic method too? Commented Mar 17, 2018 at 19:51
  • 1
    Unless you want to compute a value based on self.__food, you shouldn't even bother defining getFood; just let the user access self.food directly. Commented Mar 17, 2018 at 19:52
  • 2
    Also, "magic method" isn't a perfectly well-defined term, but it's it's usually used for methods like __init__ and __add__—with double underscores on both sides, not just the left—which are there for your class to conform to a "protocol" used by Python or the stdlib. Commented Mar 17, 2018 at 19:54
  • By the way, double underscores aren't really about hiding the variables from callers so they can't use them intentionally, but hiding them from subclasses so they can't use them accidentally. Commented Mar 17, 2018 at 19:57

1 Answer 1

4

The primary purpose of adding leading underscores is to provide something akin to "private variables" in python. Well, they aren't exactly private variables - python does not really provide this language feature. The interpreter will mangle the names, making it (slightly) harder to access these members from outside the class.

You may read more on the official documentation (2.x docs since your question is tagged as such). Relevant excerpt -

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. This mangling is done without regard to the syntactic position of the identifier, as long as it occurs within the definition of a class.

To summarise, the mangled version of a "private" variable, say __x will be _ClassName__x. You can verify this is the case for your class:

In [251]: animal['dog']._Animal__food
Out[251]: 'delicious thing you never know'

Right, so, as mentioned in my comment, the purpose of a "private member" is so that it may not be accessed outside the class. If your intention with defining this member is so that it should be accessed outside, you shouldn't even be adding the leading underscores.

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

Comments

Your Answer

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.