I am trying to understand more about the scopes of python variables.
As of now, I do not want to break or violate encapsulation on variables that are declared to be private i.e., “self._variable”.
I was wondering whether if it would be breaking encapsulation if a child class directly calls a variable from its parent class. For example:
class Parent: def __init__(): self._randomVariable = '' class Child(Parent): def__init__(): super().__init__() def doSomething(): self._randomVariable = 'Test'
Does Chid.doSomething() technically break encapsulation for directly calling self._randomVariable in its method even if it is a child class?
I couldn’t find anything that was Python specific about encapsulation but rather stuff based on Java. Is it the same idea between Java and Python?
Advertisement
Answer
Encapsulation is not as big of a deal in Python as it is in most other languages (Java, C++, et cetera), and you really shouldn’t worry about it too much. In the Python community, we have this principle that “we are all consenting adults here”.
What this means is that it’s on your responsibility if you go and mess around with someone else’s code, but also don’t prevent others from messing with your code if they really know what they’re doing. For this reason, there isn’t really private
and protected
in Python, and you shouldn’t worry about them the same way you do in Java.
But as it’s become clear by now, there is still some sort of privacy with underscores. So, what are they usually used for?
Single underscore prefixed variables (e.g. self._var
)
These are used for both private and protected variables. Prefixing your variable with an underscore is (mostly) a convention, which simply tells the reader that “this variable is used internally by this class, and should not be accessed from the outside”. Well, if your subclasses need it, they may still use it. And if you need it from outside of the class, you may still use it. But it’s on your responsibility, make sure you don’t break anything.
There are some other minor effects too, such as from module import *
not importing underscore prefixed variables, but the convention of privacy is the main point.
Double underscore prefixed variables (e.g. self.__var
)
Also known as “dunder” (double-under) variables, these are used for name mangling. The idea is that if you have a common variable name and you’re afraid that subclasses might use the same variable name for their internal stuff, you can use double underscore prefix to secure your variable from being overwritten accidentally. This way your self.__var
becomes self._BaseClassName__var
, and your subclass’s self.__var
becomes self._SubClassName__var
. Now they won’t overlap.
And while the effect can be used to simulate other languages’ private
, I recommend you not to. Again, we are all consenting adults here, just mark your variable “private” with a single underscore, and I won’t touch it unless I really know what I’m doing.