Add tech_docs/python/python_deep_dive.md

This commit is contained in:
2024-10-02 02:31:03 +00:00
parent 9e65b995e2
commit a7db2c74c2

View File

@@ -0,0 +1,106 @@
Certainly! Here's a clear **outline** that summarizes the key concepts we've discussed. You can use this as a reference to track these important items:
---
## **1. Python Naming Conventions: Double Underscore and Privacy**
### A. **Dunder (Double-Underscore) Methods**
- **Purpose**: Special system-defined methods that control object behavior with built-in functions and operators.
- **Examples**:
- `__init__()` Constructor for initializing an object.
- `__len__()` Defines length for `len()` function.
- `__str__()` Controls string representation with `str()`.
- **Usage**: You implement these methods to define or customize how objects interact with common Python operations.
### B. **Single Leading Underscore (_name) Protected Attributes**
- **Convention**: Used to indicate **protected** attributes or methods meant for internal use.
- **Access**: Accessible both within and outside the class, but its **discouraged** to access from outside.
- **Usage**: Use `_name` to signal that an attribute or method should be treated as internal, though not strictly enforced.
### C. **Double Leading Underscore (__name) Private Attributes**
- **Purpose**: Used to mark attributes as **private** and avoid accidental access, especially in subclasses.
- **Name Mangling**: Python renames `__name` to `_ClassName__name` to prevent accidental overrides.
- **Access**: Not intended for external access, though it can still be accessed using the mangled name.
- **Usage**: Use `__name` when you want to ensure that an attribute is not easily overridden in subclasses.
### D. **Double Leading and Trailing Underscore (__name__) Reserved System Methods**
- **Purpose**: Reserved for Python's system-defined methods and attributes.
- **Examples**:
- `__init__()`, `__call__()`, `__str__()`
- **Usage**: Avoid using this pattern in your own code unless youre overriding a special method.
### E. **Single Trailing Underscore (name_)**
- **Purpose**: Used to avoid conflicts with Python keywords (e.g., `class_`, `def_`).
- **Usage**: Use it to avoid naming collisions when naming attributes or variables that would otherwise conflict with reserved words.
---
## **2. Name Mangling in Python**
### A. **Definition**
- **What It Is**: A process that alters the name of attributes with **double leading underscores** (`__name`) to include the class name (`_ClassName__name`).
- **Purpose**: Prevents accidental overriding or access of private attributes from subclasses.
### B. **Example**
```python
class Parent:
def __init__(self):
self.__private_var = 42 # Becomes _Parent__private_var
```
- You can't access `__private_var` directly from outside the class, but can still access it using the mangled name (`_Parent__private_var`).
---
## **3. Differences Between Private and Protected Attributes**
### A. **Protected (_name)**
- **Convention**: Attribute is for internal use but still accessible from outside.
- **Access**: Meant for access within the class and its subclasses, though not strictly enforced.
- **Example**:
```python
class MyClass:
def __init__(self):
self._protected_var = 10
```
### B. **Private (__name)**
- **Convention**: Attribute is more "private" and is **name-mangled** to avoid accidental access or override.
- **Access**: Can only be accessed via name mangling (e.g., `_ClassName__name`).
- **Example**:
```python
class MyClass:
def __init__(self):
self.__private_var = 42 # Becomes _MyClass__private_var
```
---
## **4. Summary Table of Usage**
| **Type** | **Notation** | **Intended Usage** | **Enforced by Python?** |
|----------------------------|---------------------------|-----------------------------------------------------------------|----------------------------------------|
| **Dunder (Special)** | `__init__()`, `__len__()` | Special methods to control behavior of built-in operations. | Yes, by system convention. |
| **Protected** | `_name` | Internal use; accessible from outside but discouraged. | No, it's a convention. |
| **Private (Name Mangling)** | `__name` | Name-mangled to avoid accidental access or overriding. | Somewhat, by name mangling. |
| **Reserved System Methods** | `__name__` | Python-reserved methods and attributes. | Yes, reserved for system use. |
| **Avoid Conflicts** | `name_` | Used to avoid conflicts with reserved keywords. | No, it's a naming convention. |
---
## **5. Practical Applications and Recommendations**
### A. **When to Use Protected (`_name`)**:
- **Internal Attributes**: Use `_name` when you want to signal to other developers that an attribute or method is **internal** but may be accessed in subclasses.
- **Not Strict**: It's a convention, so its not strongly enforced. Other developers can still access these if they need to.
### B. **When to Use Private (`__name`)**:
- **Avoiding Subclass Conflicts**: Use `__name` if you want to avoid accidental overrides in subclasses.
- **More Private**: This adds a layer of protection, making it harder to access or override. However, it's still accessible through name mangling if necessary.
### C. **When to Use Dunder Methods (`__init__`, `__str__`, etc.)**:
- **Customizing Behavior**: Use dunder methods to customize how your class instances interact with Pythons built-in functions (e.g., `len()`, `str()`, `+`, `==`).
- **Keep It Simple**: Dont define your own names with leading and trailing double underscores unless you're overriding one of Pythons special methods.
---
This outline provides you with a structured way to understand and track how and when to use double underscores and underscores in Python. Let me know if you want further clarifications on any section!