[Python-ideas] Dataclasses, keyword args, and inheritance

George Leslie-Waksman waksman at gmail.com
Mon Jan 22 22:33:46 EST 2018

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:

class Foo:
    some_default: dict = field(default_factory=dict)

class Bar(Foo):
    other_field: int

this results in the error:

      5 @dataclass
----> 6 class Bar(Foo):
      7     other_field: int

in dataclass(_cls, init, repr, eq, order, hash, frozen)
    752     # We're called as @dataclass, with a class.
--> 753     return wrap(_cls)

in wrap(cls)
    744     def wrap(cls):
--> 745         return _process_class(cls, repr, eq, order, hash, init,
    747     # See if we're being called as @dataclass or @dataclass().

in _process_class(cls, repr, eq, order, hash, init, frozen)
    675                                 #  in __init__.  Use "self" if
    676                                 '__dataclass_self__' if 'self' in
--> 677                                     else 'self',
    678                                 ))
    679     if repr:

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')

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:

class Bar(Foo):
    other_field: int

--George Leslie-Waksman
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20180123/32860aa2/attachment.html>

More information about the Python-ideas mailing list