Lab 01: Metaprogramming

Objective

Master Python's metaprogramming toolkit: __init_subclass__ for automatic plugin registration, metaclasses for class-level control, descriptor factories with __set_name__, __class_getitem__ for parametric types, and dynamic class creation with type().

Background

Metaprogramming means writing code that writes or modifies code. Python exposes its entire object model at runtime, which means you can intercept class creation, customize attribute access, and build domain-specific type systems — all without external libraries.

Time

35 minutes

Prerequisites

  • Python Practitioner Labs 01 (Advanced OOP), 07 (Type Hints)

Tools

  • Docker: zchencow/innozverse-python:latest


Lab Instructions

Step 1: __init_subclass__ — Automatic Plugin Registry

💡 __init_subclass__ is called automatically whenever a class that inherits from yours is created. The keyword argument plugin_name='json' in the class definition body is passed as a **kw parameter. This pattern is how frameworks like FastAPI and SQLAlchemy auto-register things — no @register decorator or manual registry call needed.

📸 Verified Output:


Step 2: Metaclasses — Controlling Class Creation

💡 Metaclass vs __init_subclass__: use __init_subclass__ for most cases (simpler, cleaner). Use a metaclass only when you need to control the class object itself — like enforcing abstract methods at class creation time (not at instantiation), or when you need __prepare__ to customise the class namespace before the body executes.

📸 Verified Output:


Step 3: Descriptor Factory with __set_name__

📸 Verified Output:


Step 4: __class_getitem__ — Parametric Types

📸 Verified Output:


Steps 5–8: Dynamic Class Factory, __prepare__, __missing__, Capstone

📸 Verified Output:


Summary

Tool
Use case
Key method

__init_subclass__

Auto-register subclasses

Defined on base class

Metaclass

Control class creation itself

__new__, __call__

__set_name__

Descriptor knows its attribute name

Called at class definition

__class_getitem__

MyClass[T] parametric syntax

Returns new class

type(name, bases, ns)

Create class at runtime

Built-in

__prepare__

Custom class namespace

Return dict-like object

__missing__

Dict auto-init on missing key

Subclass dict

Further Reading

Last updated