pythonoopinheritancename-mangling

Getting parent private or protected values from the child class


Well, I have almost the same question, except one detail: I need to get private values of the base class. Code:

class Parent(object):
    def __init__(self):
        self.__field = 13

class Child(Parent):
    def ChildMethodWhichUsingParentField(self):
        return self.__field

c = Child()
c.ChildMethodWhichUsingParentField()

Interpreter output:

Traceback (most recent call last):
  File "foo.py", line 20, in <module>
    c.ChildMethodWhichUsingParentField()
  File "foo.py", line 16, in ChildMethodWhichUsingParentField
    return self.__field
AttributeError: 'Child' object has no attribute '_Child__field'

The problem is that interpreter tries to get _Child__field when I need _Parent__field. I can get this value using @property, but it will break the encapsulation. Also I can solve this problem writing self._Parent__field but this is ugly and obviously bad code. Is there any other ways?


Solution

  • As you have noted in the question, you can access the parent attribute by explicitly using the mangled form of its name in the child class:

    def ChildMethodWhichUsingParentField(self):
        return self._Parent__field
    

    This is the only simple answer to your direct question.

    However, if you have control over the Parent class, this would be a very bad design. You should not use a double-underscore attribute name for something that another class class will ever use (and really you probably shouldn't use it even if you don't expect any such use). Use a single underscore (_field) instead. This "documents" that the attribute is intended to be private (e.g. not part of a class's public API), without enabling name mangling. That way, if you find later than another class does need to access the variable it can. Python doesn't enforce privacy (not even when name mangling is used), so you'll always need to rely upon other code behaving nicely.

    Name mangling is really only intended for use in situations where you need to avoid name collisions. For instance, a proxy object might use mangled names for its own attributes so that it can present an interface that is an exact replica of another object's interface (which may not be known ahead of time). Or a mixin class might use name mangling for its variables since it can't know for sure what attribute names will be used in the (possibly many) other classes that will be inherited along side it. It can also be useful if you're adding an attribute for your own use to other objects (not self) and want to avoid overwriting their existing attributes by mistake.