-
1. Introduction to Python
-
2. Python Basics
-
3. Working with Data Structures
-
4. Functions and Modules
-
5. Object-Oriented Programming (OOP)
-
6. File Handling
-
7. Error and Exception Handling
-
8. Python for Data Analysis
-
9. Advanced Topics in Python
-
10. Working with APIs
-
11. Python for Automation
-
12. Capstone Projects
- 13. Final Assessment and Quizzes
5.4.1 Private and protected attributes
In Python, attributes in classes can be made private or protected using naming conventions, but it's important to note that Python does not have strict access modifiers like other languages (e.g., Java or C++). Instead, Python relies on naming conventions and name mangling to define whether an attribute is private or protected. These conventions are designed to signal the intended usage of an attribute, but they do not provide real enforcement of access control.
Let’s look at private and protected attributes in Python in more detail.
Private Attributes
- Private attributes are intended to be used only within the class and not accessed directly from outside the class.
- To define a private attribute, you prefix the attribute name with two underscores (__).
- Python will mangle the name of the attribute, making it harder to access directly from outside the class. However, it is still possible to access the private attribute using special syntax, but this is strongly discouraged.
Syntax for Private Attributes:
class MyClass: def __init__(self): self.__private_attribute = 42 # Private attribute def get_private_attribute(self): return self.__private_attribute # Getter method for private attribute
- Private attributes are often used to ensure that the internal state of an object is hidden from the outside world and can only be modified or accessed through methods (such as getters and setters).
Example of Private Attributes:
class BankAccount: def __init__(self, owner, balance): self.owner = owner # Public attribute self.__balance = balance # Private attribute def get_balance(self): return self.__balance # Getter for private attribute def set_balance(self, amount): if amount >= 0: self.__balance = amount else: print("Invalid balance amount.") # Creating an instance account = BankAccount("John Doe", 1000) # Accessing private attribute directly (will raise an error) # print(account.__balance) # AttributeError: 'BankAccount' object has no attribute '__balance' # Accessing private attribute using getter print(account.get_balance()) # Output: 1000
Name Mangling:
Python internally changes the name of a private attribute by adding _ClassName to the front of the attribute's name. This process is called name mangling and makes private attributes harder to access directly.
- The private attribute __balance in the BankAccount class will actually be stored as _BankAccount__balance.
- While this is not strictly private, it’s an indication that the attribute is meant to be private and not accessed directly.
# Accessing private attribute using name mangling (not recommended) print(account._BankAccount__balance) # Output: 1000
Protected Attributes
- Protected attributes are intended to be used within the class and its subclasses. They are not meant to be accessed from outside the class, but unlike private attributes, they can be accessed by subclasses.
- To define a protected attribute, you prefix the attribute name with one underscore (_).
Syntax for Protected Attributes:
class MyClass: def __init__(self): self._protected_attribute = 42 # Protected attribute
Example of Protected Attributes:
class Vehicle: def __init__(self, make, model): self._make = make # Protected attribute self._model = model # Protected attribute def get_info(self): return f"{self._make} {self._model}" class Car(Vehicle): def __init__(self, make, model, doors): super().__init__(make, model) self._doors = doors # Protected attribute for subclass def get_car_info(self): return f"{self.get_info()} with {self._doors} doors" # Creating an instance car = Car("Toyota", "Camry", 4) # Accessing protected attribute directly (allowed within the class or subclass) print(car._make) # Output: Toyota print(car._doors) # Output: 4
Difference Between Private and Protected Attributes:
- Private attributes (with __ prefix) are meant to be inaccessible outside the class. They are name-mangled to make direct access more difficult, signaling that they should not be used outside the class, not even by subclasses.
- Protected attributes (with _ prefix) are intended to be accessible within the class and its subclasses. Although they are meant to be protected, they are not name-mangled and can be accessed directly by subclasses, but accessing them outside the class or subclass is considered bad practice.
Summary:
-
Private attributes:
- Prefixed with __.
- Intended for internal use only within the class.
- Python uses name mangling to prevent direct access from outside the class.
- Example: self.__private_attribute.
-
Protected attributes:
- Prefixed with _.
- Intended for use within the class and its subclasses.
- Not name-mangled, so they can be accessed by subclasses but are still considered protected.
- Example: self._protected_attribute.
Best Practices:
- Use private attributes for internal state that should not be accessed or modified directly from outside the class.
- Use protected attributes for attributes that should be accessed by subclasses but not directly by other external code.
- Always try to interact with an object’s attributes through methods (getters and setters) rather than directly manipulating them. This ensures better control over how data is accessed and modified.
Commenting is not enabled on this course.