#OOP #encapsulation
[[Outcome 1 - Programming#7. principles of OOP, including| U3 - AOS1 - KK7]]
## Python Encapsulation
Encapsulation is about protecting data inside a class.
It means keeping data (properties) and methods together in a class, while controlling how the data can be accessed from outside the class.
This prevents accidental changes to your data and hides the internal details of how your class works.
## Private Properties
In Python, you can make properties private by using a double underscore `__` prefix:
Create a private class property named `__age`:
```python
class Person:
def __init__(self, name, age):
self.name = name
self.__age = age # Private property
p1 = Person("Emil", 25)
print(p1.name)
print(p1.__age) # This will cause an error
```
## Get Private Property Value
To access a private property, you can create a getter method:
### Example
Use a getter method to access a private property:
```python
class Person:
def __init__(self, name, age):
self.name = name
self.__age = age
def get_age(self):
return self.__age
p1 = Person("Tobias", 25)
print(p1.get_age())
```
## Set Private Property Value
To modify a private property, you can create a setter method.
The setter method can also validate the value before setting it:
### Example
Use a setter method to change a private property:
```python
class Person:
def __init__(self, name, age):
self.name = name
self.__age = age
def get_age(self):
return self.__age
def set_age(self, age):
if age > 0:
self.__age = age
else:
print("Age must be positive")
p1 = Person("Tobias", 25)
print(p1.get_age())
p1.set_age(26)
print(p1.get_age())
```
## Why Use Encapsulation?
Encapsulation provides several benefits:
- **Data Protection:** Prevents accidental modification of data
- **Validation:** You can validate data before setting it
- **Flexibility:** Internal implementation can change without affecting external code
- **Control:** You have full control over how data is accessed and modified
### Example
Use encapsulation to protect and validate data:
```python
class Student:
def __init__(self, name):
self.name = name
self.__grade = 0
def set_grade(self, grade):
if 0 <= grade <= 100:
self.__grade = grade
else:
print("Grade must be between 0 and 100")
def get_grade(self):
return self.__grade
def get_status(self):
if self.__grade >= 60:
return "Passed"
else:
return "Failed"
student = Student("Emil")
student.set_grade(85)
print(student.get_grade())
print(student.get_status())
```
## Protected Properties
Python also has a convention for protected properties using a single underscore `_` prefix:
### Example
Create a protected property:
```python
class Person:
def __init__(self, name, salary):
self.name = name
self._salary = salary # Protected property
p1 = Person("Linus", 50000)
print(p1.name)
print(p1._salary) # Can access, but shouldn't
```
**Note:** A single underscore `_` is just a convention. It tells other programmers that the property is intended for internal use, but Python doesn't enforce this restriction.
## Private Methods
You can also make methods private using the double underscore prefix:
### Example
Create a private method:
```python
class Calculator:
def __init__(self):
self.result = 0
def __validate(self, num):
if not isinstance(num, (int, float)):
return False
return True
def add(self, num):
if self.__validate(num):
self.result += num
else:
print("Invalid number")
calc = Calculator()
calc.add(10)
calc.add(5)
print(calc.result)
# calc.__validate(5) # This would cause an error
```
**Note:** Just like private properties with double underscores, private methods cannot be called directly from outside the class. The `__validate` method can only be used by other methods inside the class.