python-metaclasses
Table of Contents
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.
# 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
Basehas metaclassM1andDerived(Base)has metaclassM2, Python requiresM2to be a subclass ofM1 - 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
python-metaclasses.md · Last modified: by 127.0.0.1
