diff --git a/tech_docs/python/python_deep_dive.md b/tech_docs/python/python_deep_dive.md new file mode 100644 index 0000000..a027f2f --- /dev/null +++ b/tech_docs/python/python_deep_dive.md @@ -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 it’s **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 you’re 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 it’s 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 Python’s built-in functions (e.g., `len()`, `str()`, `+`, `==`). +- **Keep It Simple**: Don’t define your own names with leading and trailing double underscores unless you're overriding one of Python’s 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! \ No newline at end of file