Question: What's a pythonic way to validate the init arguments before instantiation w/o overriding dataclasses built-in init? 

I thought perhaps leveraging the `__new__` dunder-method would be appropriate? 

```
from dataclasses import dataclass

@dataclass
class MyClass:
    is_good: bool = False
    is_bad: bool = False

    def __new__(cls, *args, **kwargs):
        instance: cls = super(MyClass, cls).__new__(cls, *args, **kwargs)
        if instance.is_good:
            assert not instance.is_bad
        return instance

```

Answer: 
Define [a `__post_init__` method on the class](https://docs.python.org/3/library/dataclasses.html#post-init-processing); the generated `__init__` will call it if defined:

```
from dataclasses import dataclass

@dataclass
class MyClass:
    is_good: bool = False
    is_bad: bool = False

    def __post_init__(self):
        if self.is_good:
            assert not self.is_bad

```

This will even work when [the `replace` function](https://docs.python.org/3/library/dataclasses.html#dataclasses.replace) is used to make a new instance.
You can try this:

```py
from dataclasses import dataclass

from validated_dc import ValidatedDC

@dataclass
class MyClass(ValidatedDC):
    is_good: bool = False
    is_bad: bool = False

instance = MyClass()
assert instance.get_errors() is None
assert instance == MyClass(is_good=False, is_bad=False)

data = {'is_good': True, 'is_bad': True}
instance = MyClass(**data)
assert instance.get_errors() is None

data = {'is_good': 'bad_value', 'is_bad': True}
instance = MyClass(**data)
assert instance.get_errors()
print(instance.get_errors())
# {'is_good': [BasicValidationError(value_repr='bad_value', value_type=<class 'str'>, annotation=<class 'bool'>, exception=None)]}

# fix
instance.is_good = True
assert instance.is_valid()
assert instance.get_errors() is None

```

ValidatedDC: <https://github.com/EvgeniyBurdin/validated_dc>