Search code examples
python-3.xdictionarykeyword-argument

Default values in kwargs with class inheritance


I have two classes A and B(A). Their constructor accept the style dictionary as a keyword argument.

For A objects I want, by default, the string green to be associated to style['color'].

For B objects color defaults to red.

I came up with this solution but find it rather clumsy. Is there a more elegant way to do this?

class A:
    def __init__(self, **kwargs):
        style = kwargs.pop('style', {})
        if 'color' not in style:
            style['color'] = 'green'
        print(style)

class B(A):
    def __init__(self, **kwargs):
        style = kwargs.pop('style', {})
        if 'color' not in style:
            style['color'] = 'red'
        super().__init__(style=style, **kwargs)

A()  #  {'color': 'green'}
B()  #  {'color': 'red'}
B(style={'color': 'blue'})  #  {'color': 'blue'}

Solution

  • Try the following instead.

    It introduces a helper method to the base class called default_kwarg.

    This can be called in both cases (superclass and subclass) to set the default value of the color key.

    This approach also enables the style dict to contain other key/value pairs. I've added an extra example at the end that demonstrates this.

    class A:
        def default_kwarg(self, arg, default):
            arg = arg.pop('style', {})
            if 'color' not in arg:
              arg['color'] = default
            return arg
    
        def __init__(self, **kwargs):
            style = self.default_kwarg(kwargs, 'green')
            print(style)
    
    class B(A):
        def __init__(self, **kwargs):
            kwargs['style'] = self.default_kwarg(kwargs, 'red')
            super().__init__(**kwargs)
    
    A()  #  {'color': 'green'}
    B()  #  {'color': 'red'}
    B(style={'color': 'blue'})  #  {'color': 'blue'}
    B(style={'something': 'else'})  #  {'something': 'else', 'color': 'red'}
    

    You could also generalize this helper method quite easily to apply defaults to other keys in the dict.