[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