__init_subclass__ was introduced in PEP 487 and according to James Powell covers every use that was previously done in metaclasses (with the one exception being implementation of protocols on types). It’s main purpose was to customize subclass creation
Just to get it out of the way, let’s see the order in which these functions are called (the other functions being __new__ and __init__)
class Parent:
def __init__(self, *args, **kwargs) -> None:
print('Parent __init__')
def __new__(cls, *args, **kwargs):
print('Parent __new__')
return super().__new__(cls, *args, **kwargs)
def __init_subclass__(cls):
print('__init_subclass__')
class Child(Parent):
def __init__(self, *args, **kwargs):
print('Child __init__')
super().__init__(*args, **kwargs)
__init_subclass__
We see that __init_subclass__ is run at time of child class creation, NOT instance creation