Passing kwargs to a base classs using python attrs library

Tags: , ,



I am using the attrs python library for a child class which inherits from a non-attrs base class. I’d like to expose all of the parent parameters to the child via kwargs but cannot figure out how to go about it with attrs.

Basic example:

@attr.s
class Child(Parent):
  x = attr.ib()
  # I want to pass through the b & c params to Parent
  b = attr.ib() 
  c = attr.ib()
  y = attr.ib(default=2)
  
  # more params

  def __attrs_post_init__(self):
    super(Child,self).__init__(a=2*self.x, b=self.b, c=self.c)

class Parent(object):
  def __init__(self, a, b, c):
    self.a = a
    self.b = b
    self.c = c
    # more params

I don’t have a huge amount of discretion over the parent class but have seen challenges around default values when making it an attrs as well. Is there a way to avoid specifying all of the Parent params on the Child? If I weren’t using attrs I could do something along the lines of **kwargs_Parent and initialize like super(Child,self).__init__(a=2*x, **kwargs)

Answer

I think the best answer for cases like yours you is the upcoming (one pull request left 😳) support for __attrs_init__: https://www.attrs.org/en/latest/init.html#hooking-yourself-into-initialization

That will allow you to write:

@attr.s(init=False)
class Child(Parent):
    x = attr.ib()

    def __init__(self, x, **kw):
        super().__init__(2*x, **kw)

        self.__attrs_init__(x)

But as along as you only have one simple parameter, you can just just as well assign the attribute yourself. I’m assuming it’s just simplified though and this feature has been added for this specific use-case.

Free bonus tip: if you use @attr.s(auto_detect=True) (or the new @attr.define that sets it to True by default) it will detect your __init__ automatically and you won’t have to pass init=False.



Source: stackoverflow