9

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?

wjandrea
  • 28,235
  • 9
  • 60
  • 81
Montreal
  • 2,143
  • 5
  • 18
  • 28
  • 4
    Why don't you stop prefixing `field` with two underscores? – jonrsharpe Oct 11 '14 at 20:27
  • 2
    Single underscore is the way to go, for custom "private" members of a class. – DevLounge Oct 11 '14 at 20:36
  • @jonrsharpe, because this will brake an encapsulation. `field` is important and for inner uses only. I want to be sure that nobody can see and/or modify `field`. – Montreal Oct 11 '14 at 20:39
  • 2
    @Montreal this doesn't achieve that - Python doesn't have private attributes, we're all consenting adults here. Double underscores just invoke name mangling, which doesn't prevent deliberate external access and makes necessary access a pain (as you're experiencing). If it should be considered private, a single underscore will suffice. Name mangling is only to avoid collisions, see http://legacy.python.org/dev/peps/pep-0008/#naming-conventions. (Also, in this context, it's *"break"*.) – jonrsharpe Oct 11 '14 at 20:44
  • @jonrsharpe I know that, but I feel a little bit disappointed about this aspect of my favorite language. – Montreal Oct 11 '14 at 20:52
  • Then why are you asking? See e.g. http://stackoverflow.com/q/1641219/3001761 – jonrsharpe Oct 11 '14 at 20:54
  • I thought that there is some another way, and now I know than it doesn't. Thanks a lot for everybody! – Montreal Oct 11 '14 at 21:01
  • One option would be read-only `@property`; you don't have to implement a setter. – jonrsharpe Oct 12 '14 at 09:16
  • I've wrote about that possibility in the question. – Montreal Oct 12 '14 at 11:20

2 Answers2

8

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.

Blckknght
  • 100,903
  • 11
  • 120
  • 169
  • Are there any peps which are suggesting enforcing privacy? IMHO, it is very big python's flaw. Even bigger than low speed. – Montreal Oct 11 '14 at 22:02
  • 5
    @Montreal: The Python developer community doesn't see lack of privacy enforcement as a flaw. Indeed, it's a feature. If you really need to, you can go in and modify anything. That is very useful when things are not going as you expect and you want to inject logging into an existing class, or introspect something to debug an odd behavior. – Blckknght Oct 11 '14 at 22:08
5

This works by adding a getter

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

    def get_field(self):
        return self.__field

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

c = Child()
print c.ChildMethodWhichUsingParentField()
wjandrea
  • 28,235
  • 9
  • 60
  • 81
kums
  • 2,661
  • 2
  • 13
  • 16