On 3/16/2021 10:06 AM, Ricky Teachey wrote:
On Tue, Mar 16, 2021 at 10:03 AM Eric V. Smith <eric@trueblade.com> wrote:
On 3/16/2021 9:48 AM, Ricky Teachey wrote:
On Tue, Mar 16, 2021 at 9:23 AM Eric V. Smith <eric@trueblade.com> wrote:
On 3/16/2021 7:01 AM, Simão Afonso @ Powertools Tech wrote:
>> The problem is that if you have 1 normal parameter and 10 keyword-only
>> ones, you'd be forced to say:
>>
>> @dataclasses.dataclass
>> class LotsOfFields:
>>       a: Any
>>       b: Any = field(kw_only=True, default=0)
>>       c: Any = field(kw_only=True, default='foo')
>>       d: Any = field(kw_only=True)
>>       e: Any = field(kw_only=True, default=0.0)
>>       f: Any = field(kw_only=True)
>>       g: Any = field(kw_only=True, default=())
>>       h: Any = field(kw_only=True, default='bar')
>>       i: Any = field(kw_only=True, default=3+4j)
>>       j: Any = field(kw_only=True, default=10)
>>       k: Any = field(kw_only=True)
>>
>> That's way too verbose for me.

Here's another option I just thought of, that might have some strengths: 

@dataclasses.dataclass
class LotsOfFields:
     #  first member assumed to be kw_or_posit unless marked otherwise
     a: Any
     #  start kw only here because `mark= dataclasses.KW_ONLY`
     b: Any = field(default=0, mark=dataclasses.KW_ONLY)
     #  all members following above line continue to be kw_only
     c: Any = 'foo'
     d: Any
     e: Any = 0.0
     f: Any
     g: Any = ()
     h: Any = 'bar'
     i: Any = 3+4j
     j: Any = 10
     k: Any

I changed the kw argument name from `kw_only` to `mark`.

The idea is that every supplied member (above, members c through k) is assumed to have the same `mark` as the most recently explicitly designated field (above, member b). Or, if there has not yet been an explicitly designated `mark` for a member, the first field (above, member a) is assumed to be `dataclasses.KW_OR_POSIT` (or whatever other singleton name makes sense).

In this way we only have to use the field() call once, we can go back and forth, we eliminate a line like `_:  dataclasses.KW_OPTIONAL` that to some people might be a bit inscrutable, and we leave the door open to support positional arguments in the future (perhaps through something like `mark= dataclasses.KW_OR_POSIT`) if it becomes desirable for some reason.

I prefer the "_: dataclasses.KW_ONLY" version, because it more closely matches "def foo(a, *, b, c, d)". The "everything else is a keyword" isn't attached to one parameter, it's between parameters.

Eric


I think I prefer it, too. But what about using something like `mark=dataclasses.KW_ONLY` rather than `kw_only=True` (in the field constructor)? So it isn't an on/off switch and as to leave open the door for positional arguments? Is that door to be totally closed? I'm not here to argue in favor of it necessarily, just asking whether we really want to close the door more tightly against it than we have to.
 

I don't see how my proposal prohibits a future use of positional arguments, much as '/' was added after '*' for positional arguments for functions.

Eric