Python
__init_subclass__
Learn subclass hooks with __init_subclass__.
What is __init_subclass__?
__init_subclass__ lets a parent class be notified when a subclass is created. It is the lightweight alternative to writing a metaclass.
You define def __init_subclass__(cls, **kwargs) inside class Base. When class Dog(Base) is written, Python automatically calls Base.__init_subclass__ with cls=Dog. The super().__init_subclass__(**kwargs) call keeps the chain going. You can register or validate subclasses this way.
Configuration with kwargs
You can pass key-value pairs to __init_subclass__. Writing class Dog(Base, tag="pet") puts tag in the kwargs dict.
This gives you declarative configuration. The parent reads values from kwargs and can attach them as attributes on the subclass. The super().__init_subclass__(**kwargs) call forwards unhandled keys down the chain, so each class handles only the keys it cares about.
Exercise Register subclasses with Base
Write a Base class with a class-level list registry = []. Define __init_subclass__(cls, **kwargs): first call super().__init_subclass__(**kwargs), then append cls.__name__ to cls.registry. Define a Dog(Base) subclass. Print Base.registry.
Show example solution
# Add __init_subclass__ to Base
class Base:
registry = []
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
cls.registry.append(cls.__name__)
class Dog(Base):
pass
print(Base.registry)
Test yourself
-
Match __init_subclass__ concepts
- __init_subclass__
- Subclass hook
- cls
- The new subclass
- super()
- Keeps the chain
- **kwargs
- Extra config
-
When is __init_subclass__ called?
class Base:
def __init_subclass__(cls):
print("subclass")
class Dog(Base):
pass
- When Dog() is called
- When class Dog is defined
- When Base() is called
- When the program exits
Show answer
When class Dog is defined — __init_subclass__ fires the moment class Dog is defined; it has nothing to do with creating instances.
-
Complete the __init_subclass__ signature
def __init_subclass__(cls, ____):
super().__init_subclass__(**kw)
Show answer
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kw)
Next lesson: __class_getitem__