# Python metaclasses **Python metaclasses** are classes whose instances are classes. Just as an object is an instance of a class, a class is an instance of its metaclass. By defining a metaclass, you can intercept class creation and control how classes behave. Metaclasses let you enforce conventions (all methods must have docstrings), auto-register subclasses, generate methods, or modify class attributes at creation time. ## Example This example uses a metaclass to automatically register all subclasses and enforce required methods. ```python # run: python3 metaclasses.py # description: metaclass for subclass registration and method enforcement class Registry(type): """Metaclass that maintains a registry of subclasses.""" def __init__(cls, name, bases, dct): super().__init__(name, bases, dct) if not hasattr(cls, '_registry'): cls._registry = {} else: # Register this subclass cls._registry[name] = cls @classmethod def get(mcs, name): """Retrieve a registered class by name.""" return mcs._registry.get(name) @classmethod def all(mcs): """List all registered classes.""" return mcs._registry.copy() class Handler(metaclass=Registry): """Base handler class with registry.""" def process(self, data): raise NotImplementedError class JsonHandler(Handler): def process(self, data): return f"processing JSON: {data}" class CsvHandler(Handler): def process(self, data): return f"processing CSV: {data}" # Metaclass methods available on base class print("Registered handlers:", list(Handler.all().keys())) print(Handler.get("JsonHandler").process("test")) for name, handler_cls in Handler.all().items(): print(f" {name}") ``` ## Common patterns **`__new__` vs `__init__`**: - `__new__(mcs, name, bases, dct)`: create the class object itself - `__init__(cls, name, bases, dct)`: initialize the created class - Typically override `__new__` to modify the class before it's created **Enforcing conventions**: - Require all methods to have docstrings - Enforce naming conventions (e.g., private methods start with `_`) - Auto-generate `__repr__` or `__str__` **Auto-registration**: - Maintain registry of all subclasses - Useful for plugin systems, handlers, strategies **Modifying class attributes**: - Auto-wrap methods (add timing, caching, logging) - Generate properties from class attributes - Add descriptor methods automatically **Inheriting metaclasses**: - If `Base` has metaclass `M1` and `Derived(Base)` has metaclass `M2`, Python requires `M2` to be a subclass of `M1` - Resolve conflicts with intermediate metaclass combining them **When to avoid**: - Descriptors or decorators are usually simpler - Metaclasses are hard to debug and understand - Over 99% of code doesn't need metaclasses