Private attributes are essential attributes of a class that can only be accessed within the class itself. If you have worked with languages like Java before, you might know that private attributes are made private using the private
keyword. However, Python has no private
keyword.
A Dog class with a public attribute — name
class Dog:
def __init__(self, name):
self.name = namerocky = Dog("rocky")
print(rocky.name) # rocky
Here, in the __init__
function, we set the attribute name
to whichever name we pass in (in this case, "rocky"
). name
here is a public attribute, meaning that it can be accessed and changed from outside of the class.
rocky.name = "lucky"
# this will change rocky's name to lucky
# this is done outside of the Dog class
A Dog class with a private attribute — name
class Dog:
def __init__(self, name):
self.__name = namerocky = Dog("rocky")
Here in Python, we can make an attribute private by adding 2 underscore characters _
in front of our variable name. Here, instead of using name
, we use __name
as our variable.
print(rocky.__name)
AttributeError: 'Dog' object has no attribute '__name'
If we attempt to access the __name
private attribute from outside of the class, we get an attribute error stating that our Dog object has no such attribute.
class Dog:
def __init__(self, name):
self.__name = name def get_name(self):
return self.__namerocky = Dog("rocky")
print(rocky.get_name()) # rocky
For us to access the __name
attribute, we would normally need to create a getter method get_name
for us to access the name.
rocky.__name = "lucky"
print(rocky.get_name()) # rocky
If we set __name
to some other name outside of the class, our get_name
method would still be able to return the original name "rocky"
.
The dict attribute in objects
The __dict__
attribute in objects store all its attributes. For instance, if we set self.name
as "rocky"
here, this will be reflected in __dict__:
class Dog:
def __init__(self, name):
self.name = namerocky = Dog("rocky")
print(rocky.__dict__)# {'name': 'rocky'}
Similarly, if we add more attributes, more attributes appear in __dict__
class Dog:
def __init__(self, name, age, breed):
self.name = name
self.age = age
self.breed = breedrocky = Dog("rocky", 5, "german shepherd")
print(rocky.__dict__)# {'name': 'rocky', 'age': 5, 'breed': 'german shepherd'}
Why private attributes are not private at all
Let’s create a class with a private attribute
class Dog:
def __init__(self, name):
self.__name = namerocky = Dog("rocky)
When we use a private attribute in a class eg. __name
, it actually appears as ___Dog__name
instead of __name
. This is known as name mangling. This is what happens when we print __dict__
.
print(rocky.__dict__)
# {'_Dog__name': 'rocky'}
Despite this being a supposed private attribute, we can actually access and edit this from outside of the class!
rocky._Dog__name = "lucky"
print(rocky._Dog__name) # lucky
Private attributes in Python are not private at all!