Paul Pinterits <rawi...@gmail.com> added the comment:
> dataclasses doesn't know the signature of the base class's __init__, so it > can't know how to call it. The dataclass doesn't need to know what arguments the parent __init__ accepts. It should consume the arguments it needs to initialize its instance attributes, and forward the rest to the parent __init__. > The typical way to handle this is for the derived class to add a > __post_init__() that calls into the base class's __init__(). How is that supposed to work? Like you said, the class doesn't know what arguments its parent constructor requires. If the derived class doesn't implement a custom __init__, @dataclass will generate one with an (probably) incorrect signature. Changing the signature is pretty much the only reason why you would need to implement a custom __init__, after all. For example: ``` @dataclasses.dataclass class Foo: foo: int def __init__(self): self.foo = 5 @dataclasses.dataclass class Bar(Foo): bar: int def __post_init__(self): super().__init__() bar = Bar(1) # TypeError: __init__() missing 1 required positional argument: 'bar' ``` And even if this workaround actually worked, it would only be applicable if you *know* you're dealing with a dataclass and you'll have this problem. If you're writing something like a class decorator (similar to @dataclass), you don't know if the decorated class will be a dataclass or not. If it's a regular class, you can rely on the __init__s being chain-called. If it's a dataclass, you can't. Therefore, a class decorator that generates/replaces the __init__ method would need to take special care to be compatible with dataclasses, just because dataclasses don't follow basic OOP design principles. Consider this trivial class decorator that generates an __init__ method: ``` def log_init(cls): try: original_init = vars(cls)['__init__'] except KeyError: def original_init(self, *args, **kwargs): super(cls, self).__init__(*args, **kwargs) def __init__(self, *args, **kwargs): print(f'{cls.__name__}.__init__ was called') original_init(self, *args, **kwargs) cls.__init__ = __init__ return cls @log_init @dataclasses.dataclass class Foo: foo: int @dataclasses.dataclass class Bar(Foo): bar: int Foo(1) # Prints "Foo.__init__ was called" Bar(1, 2) # Prints nothing ``` How do you implement this in a way that is compatible with @dataclass? ---------- _______________________________________ Python tracker <rep...@bugs.python.org> <https://bugs.python.org/issue43835> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com