msg314341 - (view) |
Author: Alan Du (alan_du) |
Date: 2018-03-23 23:33 |
I'd like to request a new option to the `dataclasses.dataclass` decorator to make the `__init__` keyword-only. The two use-cases I have in mind are: (1) Using as a dataclass big-bag-of-config. In this scenario, forcing the user to specify the keywords is a lot nicer than passing in a dozen positional parameters. (2) Having kwarg-only parameters means that inheritance and default parameters play nicely with each other again instead of raising a TypeError. |
|
|
msg314342 - (view) |
Author: Alan Du (alan_du) |
Date: 2018-03-23 23:40 |
If this would be accepted, I'd be happy to contribute a patch adding a `kwarg_only` option to `dataclass` (although it might take me a while since I'm not super familiar with the Python development workflow). I believe I already have the code change necessary at https://github.com/alanhdu/cpython/commit/fa35b39e5204845690ff774812f882f40b0e5f90 (although it still needs tests and documentation). |
|
|
msg314343 - (view) |
Author: Alan Du (alan_du) |
Date: 2018-03-23 23:41 |
Err... the right link would actually be https://github.com/alanhdu/cpython/tree/bpo-33129. |
|
|
msg314346 - (view) |
Author: Eric V. Smith (eric.smith) *  |
Date: 2018-03-24 00:27 |
Changing this to 3.8: there's not enough time to add this to 3.7. |
|
|
msg316784 - (view) |
Author: Eric V. Smith (eric.smith) *  |
Date: 2018-05-16 08:26 |
I'd forgotten about this issue and created #33493. I'll close it. Copied here is my comment from that issue: I've had several requests for keyword-only arguments. This is a placeholder to remind me to work on it. I have not decided if it's a good idea or not. I propose adding a keyword_only argument to field(), defaulting to False. I'm thinking that the basic idea would be to put all keyword-only fields at the end of the arguments to __init__, but for all other uses, leave them where they appear in the class definition. That way comparison operations, in particular, would use the fields as they appear in the class definition (which is the current behavior). Since they'd be at the end of __init__, and since order doesn't matter (they're keyword-only, after all), then this would work as expected for base classes. That is, given: @dataclass class B: a: field(type=int, keyword_only=True) b: int @dataclass class C(B): c: int d: field(type=int, keyword_only=True) Then B's __init__ would take (b, c, *, a, d) as its arguments, but its comparison functions would compare the tuples as (a, b, c, d). It would be an error for a ClassVar field to be keyword-only. I think it would be okay if an InitVar field were keyword-only, but I haven't given it a lot of thought. |
|
|
msg321811 - (view) |
Author: Karthikeyan Singaravelan (xtreak) *  |
Date: 2018-07-17 10:53 |
There is an open PR and some discussion about this feature in attrs repo : https://github.com/python-attrs/attrs/pull/281 |
|
|
msg322051 - (view) |
Author: Raymond Hettinger (rhettinger) *  |
Date: 2018-07-21 00:43 |
+1 from me -- think would occasionally be nice to have. |
|
|
msg322455 - (view) |
Author: jimbo1qaz_ via Gmail (jimbo1qaz_) |
Date: 2018-07-27 01:58 |
first post in bugs.python.org... are people normally scary around here? Another usecase of keyword-only arguments is that I can mix default and non-default fields in any order. This could be achieved by either marking all fields as read-only, or by implicitly adding an asterisk before the first "conflicting" non-default argument (or by translating .../etc into an asterisk). (Is it a bad idea to create a private fork of `pip install dataclasses` with implicit asterisk, purely for my own project?) |
|
|
msg365218 - (view) |
Author: Michael Lee (wanderrful) * |
Date: 2020-03-28 16:46 |
Hello! I've submitted a PR based on this issue, since it seemed the most relevant from my searching of the backlog. Here's a link: https://github.com/python/cpython/pull/19206 |
|
|
msg374108 - (view) |
Author: Prakhar Goel (Prakhar Goel) |
Date: 2020-07-22 20:21 |
Hi, As another piece of evidence: I run into this problem _all the time_. Whenever I need a field in the parent with a default, I either need to add bogus default values for every field in every subclass or just skip the default in the parent. I'd like to suggest a middle ground: 1. A field level keyword_only option which forces just that field to be a kw-only field (for every subclass as well). 2. A class level keyword_only option that does: 2a. False (default) means current behavior where classes are not keyword only (but may be forced to be by the field specific arg). 2b. True means all the fields in this class (but not the subclasses!) Would be marked as keyword only. This does affect the order of arguments in the init method but that seems acceptable given that keyword only parameters are conceptually order independent. 2c. None implies that precisely the fields with a default (or default_factory) should be keyword only fields. Thoughts? |
|
|
msg375167 - (view) |
Author: wyz23x2 (wyz23x2) * |
Date: 2020-08-11 08:34 |
Since '/' was introduced in Python 3.8, support for positional parameters should be supported too. |
|
|
msg380746 - (view) |
Author: Etienne POT (conchylicultor) * |
Date: 2020-11-11 10:59 |
Solving this would significantly improve @dataclass inheritance (https://bugs.python.org/issue39300). Any idea when this will land ? Currently, it is not possible to add required argument to a child dataclass (unless hacks like duplicating attributes): ``` import dataclasses @dataclasses.dataclass class A: x: int = 1 @dataclasses.dataclass class B(A): y: int # ERROR: non-default argument follows default argument ``` Keywords-only would solve this issue: ``` @dataclasses.dataclass class B(A): y: int = dataclasses.field(kw_only=True) B(123, y=456) ``` Note: Attrs already support this: https://www.attrs.org/en/stable/examples.html#keyword-only-attributes For the behavior, I think there are two options: ``` class A: a0: int a1: int = field(kw_only=True) a2: int class B(A): b0: int b1: int = field(kw_only=True) b2: int ``` Option 1: All attributes following `kw_only` are `kw_only` (kw_only indicates where to place '*') A(a0, *, a1, a2) B(a0, b0, *, a1, a2, b1, b2) Option 2: `kw_only` are individually moved to the end A(a0, a2, *, a1) B(a0, a2, b0, b2, *, a1, b1) I personally prefer Option 1, as it makes it easier to place the `*` with less boilerplate. ``` class Request: url: str timeout: int = field(default=-1, kw_only=True) verify: bool = False params: Optional[Dict[str, str]] = None cookies: Optional[Dict[str, str]] = None Request(url, *, timeout=-1, verify=False, params=None, cookies=None) ``` Which looks better than: ``` class Request: url: str timeout: int = field(default=-1, kw_only=True) verify: bool = field(default=False, kw_only=True) params: Optional[Dict[str, str]] = field(default=None, kw_only=True) cookies: Optional[Dict[str, str]] = field(default=None, kw_only=True) ``` |
|
|
msg383131 - (view) |
Author: Etienne POT (conchylicultor) * |
Date: 2020-12-16 09:49 |
For the API, I think we could add this feature with a single new `dataclass(kw_only: bool | str)` ``` @dataclasses.dataclass(kw_only=True) class A: a: int b: int c: int # A(*, a, b, c) @dataclasses.dataclass(kw_only='b') class A: a: int b: int c: int # A(a, *, b, c) ``` I think this would be flexible enough for all use cases, while avoiding the boilerplate from the above proposals. |
|
|
msg388953 - (view) |
Author: Eric V. Smith (eric.smith) *  |
Date: 2021-03-17 18:21 |
Closing this in favor of issue 43532, which has a slightly elaborated approach. |
|
|