Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Advanced Python Object-Oriented Features and Best Practices

Tech 1

Customizing Instance Behavior with Special Methods

Special methods (often called "dunder" methods) enable intuitive, operator-like interactions with class instances. For example:

class DataContainer:
    def __init__(self, label: str, size: int, items: list):
        self.label = label
        self.size = size
        self.items = items

    def __len__(self):
        return self.size

    def __getitem__(self, idx):
        return self.items[idx]

    def __call__(self):
        print(f"Invoked: {self.label}")

container = DataContainer("training_set", 10, ["img_01.jpg", "img_02.jpg", "img_03.jpg"])
print(len(container))     # → 10
print(container[1])       # → "img_02.jpg"
container()               # → "Invoked: training_set"

These methods are foundational in building custom sequence-like types—commonly used in PyTorch-style Dataset implementations where __getitem__ supports indexing and __len__ reports dataset length.

Encapsulation via Name Mangling

Python uses double underscores (__) to trigger name mangling, discouraging external access to attributes and methods:

class Vehicle:
    def __init__(self, model: str):
        self.model = model
        self.__mileage = 0
        self.__log_startup()

    def update_mileage(self, km: float):
        if km >= 0:
            self.__mileage = km
        else:
            raise ValueError("Mileage cannot be negative")

    def display_mileage(self):
        print(f"Current mileage: {self.__mileage} km")

    def __log_startup(self):
        print(f"{self.model} initialized")

v = Vehicle("Tesla Model S")
v.update_mileage(15720.5)
v.display_mileage()  # → "Current mileage: 15720.5 km"

Name mangling doesn’t enforce strict privacy but signals intent and prevents accidental overrides in subclasses. Validation logic inside setter methods adds robustness unavailable with public attributes.

Property Decorators for Controlled Access

The @property decorator allows treating method calls as attribute access—improving readability while preserving encapsulation:

class Temperature:
    def __init__(self):
        self._celsius = 0.0

    @property
    def celsius(self):
        return self._celsius

    @celsius.setter
    def celsius(self, value):
        if value < -273.15:
            raise ValueError("Below absolute zero")
        self._celsius = value

    @property
    def fahrenheit(self):
        return (self._celsius * 9/5) + 32

thermo = Temperature()
thermo.celsius = 25.0
print(thermo.fahrenheit)  # → 77.0

This pattern unifies inetrface consistency: users read/write celsius like a field, while internal validation and derived computation remain fully controlled.

Class and Static Methods

@classmethod receives the class (cls) as its first argument and operates on class-level state. @staticmethod has no implicit first parameter and behaves like a regular function bundled within a class:

class DatabaseConnection:
    active_connections = 0

    def __init__(self, host: str):
        self.host = host
        DatabaseConnection.active_connections += 1

    @classmethod
    def reset_counter(cls):
        cls.active_connections = 0

    @staticmethod
    def is_valid_host(hostname: str) -> bool:
        return isinstance(hostname, str) and "." in hostname

    def close(self):
        DatabaseConnection.active_connections -= 1

DatabaseConnection.reset_counter()
print(DatabaseConnection.is_valid_host("db.example.com"))  # → True
conn = DatabaseConnection("localhost")
print(DatabaseConnection.active_connections)  # → 1

Class methods support factory patterns and shared state management; static methods group utility logic logically related to the class but independent of instance or class data.

Runtime Type and Inheritance Inspection

isinstance() and issubclass() provide safe, dynamic type checking:

class Shape:
    pass

class Circle(Shape):
    pass

class Rectangle(Shape):
    pass

shape = Shape()
circle = Circle()

print(issubclass(Circle, Shape))      # → True
print(isinstance(circle, Circle))     # → True
print(isinstance(circle, Shape))      # → True (inherits)
print(isinstance(shape, Rectangle))   # → False

These checks are essential in polymorphic dispatch, plugin systems, and defensive coding where behavior depends on object lineage.

Module and Package Import Mechanics

A directory becomes a Python package when it contains an __init__.py file (evenif empty). Consider this structure:

project/
├── core/
│   ├── __init__.py
│   ├── utils/
│   │   ├── __init__.py
│   │   └── helpers.py
│   └── models/
│       ├── __init__.py
│       └── classifier.py
└── app.py

From app.py, import using absolute paths:

from core.utils.helpers import format_timestamp
from core.models.classifier import NeuralNet

Inside classifier.py, use relative imports to reference sibling modules:

from ..utils.helpers import validate_input  # moves up one level, then into utils

Relative imports require execution context to be within a package (e.g., launched via python -m core.models.classifier). Absolute imports are preferred for clarity and maintainability in most projects.

Self-Reference in Instance Methods

Every bound instance method must declare self as its first parameter. Omitting it raises TypeError at call time because Python automatically passes the instance. This rule applies universally—even for methods with no other arguments.

Tags: Python

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.