It may be possible but it makes for pretty leaky abstractions and it's unclear what that custom __init__ should look like. How am I supposed to know what the replacement for default_factory is?
Moreover, suppose I want one base class with an optional argument and a half dozen subclasses each with their own required argument. At that point, I have to write the same __init__ function a half dozen times. It feels rather burdensome for the user when an additional flag (say "kw_only=True") and a modification to: https://github.com/python/cpython/blob/master/Lib/dataclasses.py#L294 that inserted `['*']` after `[self_name]` if the flag is specified could ameliorate this entire issue. On Wed, Jan 24, 2018 at 3:22 PM Ivan Levkivskyi <levkivs...@gmail.com> wrote: > 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 <waks...@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/ >> >> >
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/