
Private Attributes in a Python Class
In this lesson, we will discuss private attributes in a Python class.
What is a private attribute? In Python, a private attribute is generally defined as an attribute that shouldn't be directly accessible from outside the class.
In Python, attribute privacy isn't as strict as in other programming languages like Java or C++.
In Python, private attributes are more about convention, an agreement among programmers, rather than strict enforcement mechanisms.
To indicate that an attribute is private, a single underscore (`_`) or double underscore (`__`) is used before the attribute's name.
Single Underscore
A single underscore before an attribute name, like `_variable`, signals to programmers that the variable is intended for internal use within the class or module where it is defined.
However, this is just a convention and doesn't prevent direct access to the attribute.
For example, define this class:
class Polygon:
def __init__(self, side):
self._side = side # This is a protected attribute
def describe(self):
return f"The side of the polygon is {self._side}"
In this class, the presence of the underscore in the attribute "_side" indicates that it is a private attribute.
Now, create an instance of the "Polygon" class.
hexagon = Polygon(6)
To access the private attribute "_side", you need to use the describe() method.
print(hexagon.describe())
6
You can't access the attribute "side" because it doesn't exist in the class; the attribute is actually named "_side".
print(hexagon.side)
AttributeError: 'Polygon' object has no attribute 'side'. Did you mean: '_side'?
However, nothing prevents you from accessing the "_side" attribute directly, even though it's private, if you prepend an underscore to the name.
print(hexagon._side)
6
This demonstrates that in Python, the attribute is private only by convention, because access is technically possible.
It's probably less straightforward, but still possible.
Double Underscore (Name Mangling)
Using a double underscore before an attribute name, like `__variable`, causes Python to rename the attribute to incorporate the class name. This is a process known as "name mangling".
How does it work? Name mangling occurs when you prefix an attribute name with two underscores (`__`). This modifies the attribute name internally by adding the class name. For example, consider a private attribute like:
`__attribute`
If the attribute is in a class called `Class`, name mangling renames it internally to:
`_Class__attribute`
Name mangling is intended to reduce the likelihood of accidental attribute overwriting in subclasses that might have the same attribute name.
Name mangling makes it harder to access the private attribute from outside the class.
For example, define this class:
class Polygon:
def __init__(self, side):
self.__side = side # This is a protected attribute
def describe(self):
return f"The side of the polygon is {self.__side}"
Note that in this case, the attribute "__side" has two underscores at the beginning instead of one.
Now, create an instance of the class.
hexagon = Polygon(6)
You can access the private attribute "__side" using the describe() method.
print(hexagon.describe())
6
However, you can't directly access the attribute from outside, as it will raise an AttributeError.
This occurs because the attribute is no longer called "__side" since it has been renamed by name mangling.
print(hexagon.__side)
AttributeError: 'Polygon' object has no attribute '__side'
However, don't think that it's impossible to access the private attribute. Access to double underscore attributes isn't completely blocked.
Despite this transformation, you can still access the "private" attribute if you know its mangled name inside the class.
print(hexagon._Polygon__side)
6
So, even with double underscores, the private attribute is still accessible from outside the class, but the process is less intuitive and discourages casual or unauthorized access.
Why use private attributes? Using private attributes helps prevent accidental data modifications and maintain the integrity of objects. It also makes code maintenance easier, as implementation details are hidden and protected from direct access.
In summary, in Python, attribute "privacy" is more a matter of convention and good programming practice than actual restriction.
This approach promotes a trust model among programmers, typical of Python's spirit, rather than imposing rigid limits.