Python encapsulation is one of the fundamental principles of object-oriented programming that allows you to bundle data and related methods into a single unit called a class. It helps in hiding the internal details of an object and provides a controlled interface for interacting with the object. In Python, encapsulation is achieved through the use of access modifiers and property methods. Here are a few examples that illustrate encapsulation in Python:
Example 1: Private Attributes and Getter/Setter Methods
class Person: def __init__(self, name, age): self._name = name # Private attribute self._age = age # Private attribute # Getter method for name def get_name(self): return self._name # Setter method for name def set_name(self, name): self._name = name # Getter method for age def get_age(self): return self._age # Setter method for age def set_age(self, age): if age >= 0: self._age = age else: print("Age cannot be negative.") # Create a Person object person = Person("Alice", 25) # Access and modify attributes using getter and setter methods print(person.get_name()) # Output: Alice person.set_name("Bob") print(person.get_name()) # Output: Bob print(person.get_age()) # Output: 25 person.set_age(30) print(person.get_age()) # Output: 30 person.set_age(-5) # Output: Age cannot be negative.
In this example, the Person
class has private attributes _name
and _age
. To access and modify these attributes, getter and setter methods (get_name()
, set_name()
, get_age()
, set_age()
) are defined. The private attributes are denoted by a single underscore conventionally, indicating that they should not be accessed directly from outside the class. Instead, the getter and setter methods provide controlled access to these attributes.
Example 2: Property Decorators
class BankAccount: def __init__(self): self._balance = 0 # Getter method for balance using property decorator @property def balance(self): return self._balance # Setter method for balance using property decorator @balance.setter def balance(self, amount): if amount >= 0: self._balance = amount else: print("Invalid amount.") # Create a BankAccount object account = BankAccount() # Access and modify balance attribute using property methods print(account.balance) # Output: 0 account.balance = 100 print(account.balance) # Output: 100 account.balance = -50 # Output: Invalid amount.
In this example, the BankAccount
class uses property decorators to define the getter and setter methods for the balance
attribute. The @property
decorator marks the method as a getter, and the @balance.setter
decorator marks the method as a setter. This allows us to access and modify the balance
attribute as if it were a regular attribute, while the getter and setter methods control the access and modification logic.
Conclusion:
Encapsulation helps in maintaining data integrity, controlling access to attributes, and providing a clean interface for interacting with objects. By encapsulating data and methods within a class, you can create more robust and maintainable code.