# Encapsulation

* Encapsulation is an essential concept in object-oriented programming that promotes data hiding and helps maintain code integrity.
    
* In Python, although there are no strict access modifiers like in some other languages, developers can use naming conventions to indicate the intended visibility of class members.
    

### Private Members

* Private members in Python are denoted by a double underscore (`__`) prefix before the variable or method name.
    
* By convention, this prefix indicates that the member is intended for internal use within the class and should not be accessed directly from outside.
    

**Example:**

```python
class MyClass:
    def __init__(self):
        self.__private_var = 100

    def __private_method(self):
        print("This is a private method.")

    def public_method(self):
        self.__private_method()
        print(f"The private variable value is: {self.__private_var}")


obj = MyClass()
obj.public_method()
```

```python
This is a private method.
The private variable value is: 100
```

In the above example, `__private_var` and `__private_method` are private members of the `MyClass` class. They are accessed within the class using the double underscore prefix. If we want to access the private variable from outside like `obj.__private_method()` then it shows **AttributeError**

### Protected Members

* Protected members in Python are denoted by a single underscore (`_`) prefix before the variable or method name.
    
* By convention, this prefix suggests that the member is intended to be used within the class and its subclasses.
    
* Though protected members can still be accessed from outside the class, developers should treat them as non-public, discouraging direct access.
    

**Example:**

```python
class BaseClass:
    def __init__(self):
        self._protected_var = 10

    def _protected_method(self):
        print("This is a protected method.")

class SubClass(BaseClass):
    def access_protected(self):
        print(f"The protected variable value is: {self._protected_var}")
        self._protected_method()


obj = SubClass()
obj.access_protected()
```

In this example, `_protected_var` and `_protected_method` are protected members within the `BaseClass`. They are accessible within the **class** and its **subclasses**.
