Search code examples
pythonimmutabilitysuperpython-dataclassespython-attrs

Passing parameters to frozen super dataclass


I have a simple (frozen) dataclass inheritance as follows:

from attrs import frozen

@frozen
class Interval:
    left: str
    right: str

@frozen
class RealInterval(Interval):
    def __attrs_pre_init__(self) -> None:
        super().__init__("-oo", "+oo")

x = RealInterval()

According to the documentation, it looks promising:

attrs_pre_init is automatically detected and run before attrs starts initializing. This is useful if you need to inject a call to super().init()

But when I check with mypy I get:

$ mypy example.py 
example.py:13: error: Missing positional arguments "left", "right" in call to "RealInterval"
Found 1 error in 1 file (checked 1 source file)

Note that this is not a duplicate of this:


Solution

  • This is not how attrs (and for that matter: dataclasses work).

    The __init__ is written for specifically the attributes you're defining for performance reasons.

    The easiest solution for your use-case is overriding the attributes:

    @frozen
    class RealInterval(Interval):
        left: str = "-oo"
        right: str = "+oo"
    

    Which gives you:

    >>> RealInterval()
    RealInterval(left='-oo', right='+oo')
    >>> RealInterval("foo", "bar")
    RealInterval(left='foo', right='bar')
    

    The pre_init logic is when you're subclassing classes you don't own, but that need their __init__ called. That's true for some GUI kits for example.