🏠 VisualStudioTutor.com  Β·  Python Tutorial Home  Β·  Python Lesson 34 of 40
Lesson 34 of 40 Advanced Python Expert ⏱ 35 min

Metaprogramming β€” __dunder__, slots & meta

Go deep into Python's object model β€” metaclasses, __init_subclass__, __class_getitem__, descriptors, and runtime class manipulation.

Part 1: What You Will Learn

  • Use common dunder methods to customise object behaviour.
  • Understand how __slots__ restricts instance attributes.
  • Register subclasses automatically with __init_subclass__.
  • See how metaprogramming can build plugin systems without manually maintaining a registry.

Part 2: Key Concepts

Metaprogramming is code that changes, creates, or configures program structures. Python exposes many hooks through special methods. These techniques are powerful, so they should be used when they simplify a framework or reusable componentβ€”not merely to make ordinary code more clever.

Part 3: Topic-Specific Code Example

class ReportPlugin:
    registry: dict[str, type["ReportPlugin"]] = {}

    def __init_subclass__(cls, *, name: str, **kwargs) -> None:
        super().__init_subclass__(**kwargs)
        ReportPlugin.registry[name] = cls
        cls.plugin_name = name

    def generate(self, data: list[int]) -> str:
        raise NotImplementedError

class SummaryReport(ReportPlugin, name="summary"):
    __slots__ = ()

    def generate(self, data: list[int]) -> str:
        return f"Count={len(data)}, Total={sum(data)}"

class AverageReport(ReportPlugin, name="average"):
    __slots__ = ()

    def generate(self, data: list[int]) -> str:
        return f"Average={sum(data) / len(data):.2f}"

def create_report(name: str) -> ReportPlugin:
    plugin_class = ReportPlugin.registry[name]
    return plugin_class()

numbers = [12, 18, 25, 30]

for name in ReportPlugin.registry:
    report = create_report(name)
    print(name, "->", report.generate(numbers))

print("Registered:", ReportPlugin.registry)

Part 4: How the Example Works

Whenever a subclass of ReportPlugin is created, __init_subclass__() automatically stores it in the registry. This is a simple form of metaprogramming because class creation itself triggers configuration. The concrete plugins use __slots__ = () because they do not need per-instance attributes.

Part 5: Hands-On Practice

Mini project β€” Command Plugin System. Create a base Command class that automatically registers subclasses such as HelloCommand, DateCommand, and HelpCommand. Let the user type a command name and instantiate the matching class from the registry.

Part 6: Next Steps

Experiment with __repr__, __len__, and class registration, then continue to Lesson 35 for profiling and performance optimisation.

πŸ“˜ Want the complete guide with projects? Get the book β†’