Prefer init_subclass or decorators; reach for a metaclass only for inheritance-wide or deep control
The PEP 487 guidance is clear: init_subclass should cover most cases where you previously needed a metaclass, because it is a normal classmethod hook that runs on every subclass. Class decorators are even simpler and apply to a single class. Metaclasses remain the right choice when you need to control the class namespace before the class object exists, customize prepare, interact with the metaclass itself (for example subclassing ABCMeta), or affect every class in a hierarchy in a way that must be part of type identity. If you find yourself writing a metaclass only to register subclasses or validate methods, you are probably over-engineering.
init_subclass: best for per-subclass validation, registration, and hooking into class creation without changing type identity.
Class decorator: best for a single class transformation, easy to apply and remove, plays well with type checkers.
Metaclass: best when you must customize the class namespace via prepare, or when your feature must be part of the class's type.
Trade-off: metaclasses compose poorly. Combining two metaclasses requires a shared subclass, which is intrusive for library consumers.
Common mistake: using a metaclass for singleton, registry, or attribute validation, all of which init_subclass or descriptors handle more cleanly.
Version note: init_subclass and set_name were added in 3.6 precisely to reduce metaclass usage. PEP 487 documents the intent.
0-2 years experience
2-5 years experience
5-8 years experience
8+ years experience