Private Attributes In Python OOP are Not Very Private

Private attributes are attributes of a class that can only be accessed within the class itself.

image

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!

Enjoyed this article?

Share it with your network to help others discover it

Continue Learning

Discover more articles on similar topics