There are, however, ways to emulate private variables and methods in Python. You can hamper access from outside their classes by applying the following conventions outlined in PEP 8:
Single leading underscore "_"
Prefixing a variable or method name with "_" (single underscore) indicates its intended for internal use and should not be accessed from outside the class in which it was defined.
class MyClass(variable):
def __init__(self):
self._meditation = 'zazen' # Notice the single leading underscore
This is just a convention and will not actually stop us from accessing the variable or method from outside. However, it's advisable to follow this convention as ignoring it can cause a lot of problems.
>>> obj = MyClass()
>>> obj._meditation
'zazen'
Notice that the _meditation attribute is accessible because it was only hidden by convention.
Caveats:
- Functions that provide internationalization and localization, used to prefix strings that need translation, are frequently named "_". Avoid confusing this with the "private" variables discussed in this post.
Double leading underscore "__"
Python has a feature called name mangling. When variables are prefixed with "__" (double underscore), their names are automatically changed into _<className><variableName>, so they are not easily accessible from outside their classes.
class MyClass(variable):
def __init__(self):
self.__meditation = 'zazen' # Notice the double leading underscore
Now let's try to access it from outside the class:
>>> obj = MyClass()
>>> obj.__meditation
AttributeError: 'MyClass' variable has no attribute '__meditation'
t.__meditation was not found because its name was automatically changed (mangled) to _MyClass__meditation. We could still access it with the syntax below:
>>> obj._MyClass__meditation
'zazen'
The example above is used to illustrate how "private" variables or methods can be accessed outside their classes. This does not mean we should do it as it will most likely wreak all sorts of havoc.
Another example:
class Glass:
def __init__(self):
self.__status = None # Notice the double leading underscore
def fill(self):
self.__status = 'filled'
def empty(self):
self.__status = 'empty'
def print(self):
print(self.__status)
In the example above, the __status attribute of the Glass class can only be set by the empty() and fill() methods. Let's test it:
>>> g = Glass()
>>> g.print()
None
>>> g.fill()
>>> g.print()
filled
>>> g.empty()
>>> g.print()
empty
In real code, "private" variables like these are used mostly to avoid clashes of names defined within classes with names defined within their subclasses.
Caveats:
- Python's "magic" variables or attributes are also prefixed with double underscore (e.g., __init__, __import__ or __file__). In this context, the double underscore prefix has no "privatizing" effect. Avoid confusing this with the "private" variables discussed in this post.