What are public, protected, & private access modifiers in Python?

Key takeaways:

  • Access modifiers control access to a class’s variables and methods.

  • Access modifiers come in three varieties: private, protected, and public.

  • Public members are accessible from any part of the program.

  • The class and its derived classes can access protected members.

  • Private members are only accessible within the class that defines them.

  • The use of access modifiers contributes to better maintainability and code encapsulation.

Object-oriented programming languages (OOP) are powerful tools that allow programmers to model real-world entities and their interactions. OOP helps organize and structure code into reusable components for improved modularity by combining data and actions into objects. It aids in managing complexity by breaking down problems into smaller units, improving code reusability through inheritance and polymorphism, and enhancing maintainability and extensibility through encapsulation. Additionally, OOP implements data abstraction to protect data integrity.

Data encapsulation and access control

A fundamental principle in OOP is data encapsulation, which focuses on controlling access to the internal components of a class. By encapsulating data, the class hides its internal state and only exposes necessary interfaces for interaction. This principle helps maintain data integrity by ensuring that data can only be accessed or modified in controlled ways.

Access modifiers in OOP languages

Most OOP languages like C++ and Java use access modifiers to control access to class members (variables and methods). These modifiers typically include:

  • Public access modifiers: Accessible from anywhere.

  • Protected access modifiers: Accessible within the class and by subclasses.

  • Private access modifiers: Accessible only within the class.

Python’s approach to access control

Python does not have built-in access modifiers like C++ or Java. All class variables and methods are public by default. However, Python follows a convention to imitate access control by prefixing variable/method names with underscores.

Using underscores for access control

In Python, we can control the perceived accessibility of variables and methods by adding underscores to their names:

  • Single underscore (_): Indicates that a variable or method is intended for internal use and should not be accessed directly.

  • Double underscore (__): Changes the variable name to make accessing from outside the class harder but not impossible.

This convention helps maintain the principles of data encapsulation in Python despite the absence of formal access modifiers.

Access Modifier

Naming Convention

Purpose

Public

No underscores

Accessible from anywhere (inside or outside the class).

Protected

Single underscore (_)

Intended for internal use within the class and its subclasses. Access outside is discouraged.

Private

Double underscore (__)

Meant for internal use only within the class.

1. Public access

By default, all members (instance variables and methods) are public. This means that all variables and methods declared inside the class can be accessed by the class itself or anywhere outside of that specific class. Let’s see an example below:

class Person:
def __init__(self, name, age):
self.name = name # public
self.age = age # public

The above class has two different member variables (name and age). These variables can be accessed directly from an instance of the Person class. This is demonstrated below:

class Person:
def __init__(self, name, age):
self.name = name # public attribute
self.age = age # public attribute
def display_info(self):
print(f"Name: {self.name}, Age: {self.age}")
# Create an object of Person
person = Person("Educative", 21)
# Accessing public attributes
print("Name:", person.name) # Direct access allowed
print("Age:", person.age) # Direct access allowed
person.display_info() # Access through method

2. Protected access

To protect an instance variable or method, the convention is to prefix the name with a single underscore _. This is demonstrated below:

class Person:
def __init__(self, name, age):
self._name = name # protected
self._age = age # protected

The member variables for the Person class in the code shown above have the prepended underscore (_). This means that the member variables can only be accessed within the class they’re defined in and in the subclasses of the parent class.

Note: An important thing to note here is that when the variable is accessed without the underscore (_) within the same class, the interpreter will not check for access modifiers because accessibility inside the same class is allowed.

class Person:
def __init__(self, name, age):
self.name = name # public attribute
self._age = age # protected attribute (convention)
def display_info(self):
print(f"Name: {self.name}, Age: {self._age}")
# Create an object of Person
person = Person("Educative", 21)
# Accessing protected attributes (allowed but discouraged)
print("Name:", person.name) # Direct access allowed (public)
print("Age:", person._age) # Direct access allowed but discouraged (protected)
person.display_info() # Access through method
# Example with subclass accessing protected attribute
class Student(Person):
def display_student_info(self):
print(f"Student Name: {self.name}, Age: {self._age}")
student = Student("Educative", 21)
student.display_student_info() # Accessing protected attribute within subclass

3. Private access

We can make an instance variable or method private by using the double underscore __, as shown below:

class Person:
def __init__(self, name, age):
self.__name = name # private
self.__age = age # private

Making a class’s member variables private can only be used inside the class. The __age instance variables cannot be accessed outside the class; doing so will give an AttributeError.

class Person:
def __init__(self, name, age):
self.name = name # public attribute
self.__age = age # private attribute (name mangling)
def display_info(self):
print(f"Name: {self.name}, Age: {self.__age}")
# Create an object of Person
person = Person("Educative", 21)
# Accessing public attribute (allowed)
print("Name:", person.name)
# Attempting to access private attribute will raise an AttributeError
try:
print("Age:", person.__age) # This will raise an AttributeError
except AttributeError as e:
print(f"Error: {e}")
person.display_info() # Access through method
# Accessing private attribute via name mangling (not recommended)
print("Age (via name mangling):", person._Person__age) # Accessing the private attribute using name mangling

Note: You can still access the private members outside the class. Python performs name mangling, so every member prefixed with __ is changed to _class__member.

All access modifiers demonstration

To demonstrate each access modifier, we create a Person class with three members: name (public), _age (protected), and __height (private). Next, we make an instance of Person and try accessing its members:

class Person:
def __init__(self, name, age, height):
self.name = name # public
self._age = age # protected
self.__height = height # private
p1 = Person("John", 20, 170)
print(p1.name) # public: can be accessed
print(p1._age) # protected: can be accessed but not advised
# print(p1.__height) # private: will give AttributeError

Try running the code with the last line uncommented print(p1.__height). You will notice it gives an AttributeError since you cannot access a private class member outside the class.

Learn the basics with our engaging Learn Python course!

Start your coding journey with Learn Python, the perfect course for beginners! Whether exploring coding as a hobby or building a foundation for a tech career, this course is your gateway to mastering Python—the most beginner-friendly and in-demand programming language. With simple explanations, interactive exercises, and real-world examples, you’ll confidently write your first programs and understand Python essentials. Our step-by-step approach ensures you grasp core concepts while having fun. Join now and start your Python journey today—no prior experience is required!

Frequently asked questions

Haven’t found what you were looking for? Contact Us


What are private attributes in Python?

Private attributes in Python are defined with a double underscore prefix (__attribute) to limit direct access from outside the class.


What are public attributes in Python?

Public attributes in Python are variables that belong to an object and can be accessed directly from outside the class. They are not restricted in access and can be freely modified.


How many attributes are there in Python?

There are no predefined fixed number of attributes in Python. Attributes are dynamically added to objects during runtime.


What is `__init__` in Python?

The __init__ is a special method in Python that is called when a new object (instance) of a class is created. It is used to initialize the attributes of the object with specific values.


Is `__init__` private in Python?

No, __init__ is not private in Python. It is a special method, often referred to as the constructor, and it is intended to initialize an object when it is created. However, by default, methods in Python are public, meaning they can be accessed from outside the class unless explicitly made private by convention.


Free Resources

Copyright ©2025 Educative, Inc. All rights reserved