[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