When I read Python Cookbook 3Edition recipe 9.18, I run into a class definition with parent Class and some optional argument, when I look it up, I know that python 3.6 add a new feature __init_subclass__() method for parent class, but the book is written based on Python3.3, so what method will take these arguments other than a metaclass
the class definition is here:
class Spam(Base, debug=True, typecheck=False):
...
I know that metaclass can accept other optional arguments in its' __prepare__, __new__, __init__ method, but Base is a parent class, where do these argument go
They go to the metaclass's __prepare__
method, just like always. Just because Base
hasn't specified a metaclass doesn't mean it doesn't have one. The default metaclass is type
.
The addition of __init_subclass__
to type
in Python 3.6 just saves you the effort of defining a custom metaclass in order to implement an equivalent to __init_subclass__
yourself.
The __init_subclass__
is an addition to Python 3.6 to reduce the need for custom metaclasses, as many of its uses are "overkill".
The idea is that each subclass that is created for a (normal, non-meta) base-class that contains an __init_subclass__
method, it willbe called, with the new subclass as first parameter:
class Base:
def __init_subclass__(subclass, debug=None, typecheck=None, **kwargs):
# do stuff with the optional debug and typecheck arguments
# Pass possible arguments not consumed here to superclasses, if any:
super().__init_subclass__(**kwargs)
And there is no need for a metaclass at all - the __prepare__
, __init__
and __new__
of the default metaclass - type
- will ignore any named argument passed in this way. But the default __init_subclass__
in object will raise if unknown named arguments reach it - the pattern above will consume these arguments, removing them from kwargs. If you are dealing with unknown named arguments, just process kwargs like a normal dictionary - no need for explicit named parameters in the __init_subclass__
.