In Python, attributes (variables inside a class) can be categorized as global (public), protected, or private, based on how accessible they are from outside the class. Python doesn’t enforce strict access control like some other languages, but it follows naming conventions to indicate intended visibility.
1. Global / Public Attributes #
- Accessible from anywhere, both inside and outside the class.
- No underscores in the name.
- Default visibility in Python.
class Employee:
def __init__(self, name):
self.name = name # public attribute
emp = Employee("Aswini")
print(emp.name) # accessible directly → "Aswini"
✅ Use case: Attributes meant to be openly accessed, like name, id, or salary.
- Protected Attributes
Intended to be used only within the class and its subclasses.
Denoted by a single underscore _ before the name.
This is only a convention; Python does not enforce protection.
class Employee:
def __init__(self, salary):
self._salary = salary # protected attribute
class Manager(Employee):
def show_salary(self):
print(self._salary) # accessible in subclass
emp = Employee(5000)
print(emp._salary) # possible but discouraged
✅ Use case: Attributes that should not be modified outside the class but might still be needed for inheritance.
3. Private Attributes #
- Intended to be hidden from outside the class.
- Denoted by double underscores
__. - Python performs name mangling, which changes
__attrto_ClassName__attrinternally.
class Employee:
def __init__(self, id):
self.__id = id # private attribute
emp = Employee(101)
# print(emp.__id) # Error: AttributeError
print(emp._Employee__id) # works due to name mangling
✅ Use case: Attributes that must be hidden and protected from accidental access, like passwords, account numbers, or sensitive internal states.
Summary Table #
| Attribute Type | Syntax | Accessibility | Notes |
|---|---|---|---|
| Public | name | Anywhere | Default in Python |
| Protected | _name | Class & subclasses (by convention) | Not enforced; “shouldn’t touch” |
| Private | __name | Class only (name mangled) | Avoid direct access; truly internal |
Real-World Example #
In a banking system:
class BankAccount:
def __init__(self, owner, balance):
self.owner = owner # public
self._pin = 1234 # protected
self.__balance = balance # private
def deposit(self, amount):
self.__balance += amount
def get_balance(self):
return self.__balance
owner → anyone can see
_pin → subclasses or internal modules can access
__balance → hidden from external access, controlled via methods
Challenges and Limitations
Python does not strictly enforce protection—developers can still access protected or private attributes.
Overuse of private attributes can reduce flexibility, especially in inheritance.
Alternative: Use property decorators (@property) for controlled access instead of relying solely on private attributes.
