It is possible to pass init=False to the decorator on the subclass (and supply your own custom __init__, if necessary): @dataclass class Foo: some_default: dict = field(default_factory=dict) @dataclass(init=False) # This works class Bar(Foo): other_field: int -- Ivan On 23 January 2018 at 03:33, George Leslie-Waksman <waksman@gmail.com> wrote:
The proposed implementation of dataclasses prevents defining fields with defaults before fields without defaults. This can create limitations on logical grouping of fields and on inheritance.
Take, for example, the case:
@dataclass class Foo: some_default: dict = field(default_factory=dict)
@dataclass class Bar(Foo): other_field: int
this results in the error:
5 @dataclass ----> 6 class Bar(Foo): 7 other_field: int 8
~/.pyenv/versions/3.6.2/envs/clover_pipeline/lib/python3.6/site-packages/dataclasses.py in dataclass(_cls, init, repr, eq, order, hash, frozen) 751 752 # We're called as @dataclass, with a class. --> 753 return wrap(_cls) 754 755
~/.pyenv/versions/3.6.2/envs/clover_pipeline/lib/python3.6/site-packages/dataclasses.py in wrap(cls) 743 744 def wrap(cls): --> 745 return _process_class(cls, repr, eq, order, hash, init, frozen) 746 747 # See if we're being called as @dataclass or @dataclass().
~/.pyenv/versions/3.6.2/envs/clover_pipeline/lib/python3.6/site-packages/dataclasses.py in _process_class(cls, repr, eq, order, hash, init, frozen) 675 # in __init__. Use "self" if possible. 676 '__dataclass_self__' if 'self' in fields --> 677 else 'self', 678 )) 679 if repr:
~/.pyenv/versions/3.6.2/envs/clover_pipeline/lib/python3.6/site-packages/dataclasses.py in _init_fn(fields, frozen, has_post_init, self_name) 422 seen_default = True 423 elif seen_default: --> 424 raise TypeError(f'non-default argument {f.name!r} ' 425 'follows default argument') 426
TypeError: non-default argument 'other_field' follows default argument
I understand that this is a limitation of positional arguments because the effective __init__ signature is:
def __init__(self, some_default: dict = <something>, other_field: int):
However, keyword only arguments allow an entirely reasonable solution to this problem:
def __init__(self, *, some_default: dict = <something>, other_field: int):
And have the added benefit of making the fields in the __init__ call entirely explicit.
So, I propose the addition of a keyword_only flag to the @dataclass decorator that renders the __init__ method using keyword only arguments:
@dataclass(keyword_only=True) class Bar(Foo): other_field: int
--George Leslie-Waksman
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/