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

George Leslie-Waksman waksman at gmail.com
Thu Jan 25 01:38:54 EST 2018


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 <levkivskyi at 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 <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/20180125/47ca7f14/attachment-0001.html>


More information about the Python-ideas mailing list