[Python-ideas] Dataclasses, keyword args, and inheritance
Ivan Levkivskyi
levkivskyi at gmail.com
Wed Jan 24 18:22:06 EST 2018
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 at 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 at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20180124/f63b590d/attachment.html>
More information about the Python-ideas
mailing list