Search code examples
pythoninheritancemetaclass

Adding argument in class definition


I ran across this design pattern in Python wondering if someone can explain as I've never seen it before

def func():
   pass

class Child(Parent, f=func):
   pass

Not sure what's happening here. Could this work if Parent has metaclass definition in which it changes the class constructor to allow for passing an argument through? Any help is appreciated and sorry for the vagueness


Solution

  • Extra named arguments in the class definition are passed into the class constructor methods - i.e., the metaclass __new__:

    In [1]: class M(type):
       ...:     def __new__(metacls, name, bases, namespace, **kwargs):
       ...:         print(f'At metaclass, {kwargs}')
       ...:         return super().__new__(metacls, name, bases, namespace)
       ...:     
    
    In [2]: class A(metaclass=M, f="hello world"): pass
    At metaclass, {'f': 'hello world'}
    

    So, a custom metaclass might make use of that, even before Python 3.6. But n Python 3.6, the __init_subclass__ addition makes it much simpler and therefore useful, to have such arguments - as no custom metaclass is needed.

    Note that the __init_subclass__ method in a custom class hierarchy is responsible to ultimately call object.__init_subclass__ - which do not take any named arguments. So, if you are creating a class hierarchy that makes use of __init_subclass__, each such method should "consume" its specific arguments by removing them from kwargs before calling super().__init_subclass__. The __new__ and __init__ methods from type itself (the default metaclass) simply ignore any named args.