2

I have a large program with multiple classes.

class Dog(object):    
    def __init__(self):
        self.food = 10

    def print_dog_food(self):
        print(self.food)


class Cat(object):    
    def __init__(self):
        self.food = 5

    def print_cat_food(self):
        print(self.food)

They are inherited by other classes:

class AllAnimals(Cat, Dog):
    def __init__(self):
        Cat.__init__(self)
        Dog.__init__(self)

Some variables will be having similar names. I am afraid of accidentally overriding an existing variable and creating nasty bugs:

# Wrong result. 
AllAnimals().print_cat_food()  # prints 10
AllAnimals().print_dog_food()  # prints 10

Keeping track of all those variables to avoid accidents seems impractical, so I was thinking of using mangling:

def __init__(self):
    self.__food = ...... 

and get what i expect:

# Correct result.
AllAnimals().print_cat_food()  # prints 5
AllAnimals().print_dog_food()  # prints 10

Mangling solves my problem, but reading this highly upvoted answer stating that:

If you want to use it eventually, you can, but it is neither usual nor recommended.

and the "This is culture" section of that answer makes me sceptical.

Questions:
- Should I use mangling as in the example?
- If not, what are my alternatives to avoid accidental overriding of variables?

Community
  • 1
  • 1
user
  • 5,370
  • 8
  • 47
  • 75
  • 1
    `Cat` and `Dog` should inherit from a class `Animal`, not the other way around. – chepner May 01 '15 at 21:53
  • @chepner Why? (i was simply trying to create a simple example of a class inheriting from 2 others) – user May 01 '15 at 21:58
  • @user5061 because [inheritance](http://en.wikipedia.org/wiki/Inheritance_%28object-oriented_programming%29) (subtyping, more specifically) is generally used to establish an `is-a` relationship. `Car` is a (special type of) `Vehicle`. `Teacher` is a `Person`. -> `Subclass` is special type of `Superclass`. – Lukas Graf May 01 '15 at 22:06
  • And specific to this example, an `Animal` is not a type of `Dog`; a `Dog` is a type of `Animal`. – chepner May 01 '15 at 22:13
  • @LukasGraf I did not pick correct names for my classes I guess. I ll edit tomorrow with more suitable names. – user May 01 '15 at 22:14
  • 1
    I had posted the answer you linked. Sorry if my answer caused confusion - it was a poor choice of words! In fact, your use case exactly the one which would be perfectly solved with double underscores. Use them! – brandizzi May 13 '15 at 23:56

2 Answers2

3

Using mangling to produce 'private' attributes is neither usual nor recommended, because there is no such thing as truly private attributes in Python.

Using mangling for what it was designed to do, reduce the likelyhood of subclasses clashing on attribute names, is absolutely pythonic and fine.

From the documentation:

Names in this category, when used within the context of a class definition, are re-written to use a mangled form to help avoid name clashes between “private” attributes of base and derived classes.

Emphasis mine.

However, the use-case is pretty rare; there are not many situations where you want the attribute to not be accidentally overridden. But if you are building base classes that are going to be widely subclassed (in a large project or as part of a framework or library intended for a wide range of uses), then using double-underscore names for implementation details is perfectly fine.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • I didn't know this is what mangling was created for. So the linked post discourages mangling only when used to hide everything for no real reason? – user May 01 '15 at 21:49
  • @user5061: that's my take on it, yes. – Martijn Pieters May 01 '15 at 21:50
  • _"..use-case is pretty rare.."_- Isn't a large program with (some) similar names one of those cases? Am i doing something wrong? – user May 01 '15 at 22:13
  • @user5061: the Python standard library reserves the use for classes that are expected to be widely subclassed and where 3rd parties should not need to know the internal implementation. The `__name` convention then is used in situations you want to support arbitrary subclassing where altering the base class is not feasible. If you have a large project being developed by multiple teams of developers then using the convention is a good use case. – Martijn Pieters May 02 '15 at 12:59
0

It is unusual, because what you're doing here is unusual. However, given your requirements, I would say that using name-mangled variables is a perfectly appropriate thing to do.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895