4.4. Dataclass KWonly
4.4.1. SetUp
>>> from dataclasses import dataclass, field, KW_ONLY
4.4.2. Problem
>>> @dataclass
... class User:
... firstname: str
... lastname: str
... is_active: bool
... is_staff: bool
... is_superuser: bool
Positional only:
>>> User('Alice', 'Apricot', True, True, False)
User(firstname='Alice', lastname='Apricot', is_active=True, is_staff=True, is_superuser=False)
Mixed:
>>> User('Alice', 'Apricot', is_active=True, is_staff=True, is_superuser=False)
User(firstname='Alice', lastname='Apricot', is_active=True, is_staff=True, is_superuser=False)
Keyword only:
>>> User(firstname='Alice', lastname='Apricot', is_active=True, is_staff=True, is_superuser=False)
User(firstname='Alice', lastname='Apricot', is_active=True, is_staff=True, is_superuser=False)
While this is flexible, it can lead to mistakes. For example, if the
is_superuser and is_staff fields are accidentally swapped.
It is very easy to do this when there are many boolean fields.
The same applies to fields of other types like int or float.
4.4.3. All Fields
Since Python 3.10
Mark all fields as keyword-only
kw_only=Falseby default
If true, then all fields will be required to be keyword-only. If a field
is set as keyword-only, then the only affect is that the __init__()
parameter generated from a keyword-only field must be specified with a
keyword when __init__() is called. There is no effect on any other
aspect of dataclasses.
>>> @dataclass(kw_only=True)
... class User:
... firstname: str
... lastname: str
... is_active: bool
... is_staff: bool
... is_superuser: bool
Positional only:
>>> User('Alice', 'Apricot', True, True, False)
Traceback (most recent call last):
TypeError: User.__init__() takes 1 positional argument but 6 were given
Mixed:
>>> User('Alice', 'Apricot', is_active=True, is_staff=True, is_superuser=False)
Traceback (most recent call last):
TypeError: User.__init__() takes 1 positional argument but 3 positional arguments (and 3 keyword-only arguments) were given
Keyword only:
>>> User(firstname='Alice', lastname='Apricot', is_active=True, is_staff=True, is_superuser=False)
User(firstname='Alice', lastname='Apricot', is_active=True, is_staff=True, is_superuser=False)
4.4.4. Particular Field
Since Python 3.10
keyword-only
If true, this field will be required as keyword-only. This is used when
the generated __init__() method's parameters are computed.
>>> @dataclass
... class User:
... firstname: str
... lastname: str
... is_active: bool = field(kw_only=True)
... is_staff: bool = field(kw_only=True)
... is_superuser: bool = field(kw_only=True)
Positional only:
>>> User('Alice', 'Apricot', True, True, False)
Traceback (most recent call last):
TypeError: User.__init__() takes 3 positional arguments but 6 were given
Mixed:
>>> User('Alice', 'Apricot', is_active=True, is_staff=True, is_superuser=False)
User(firstname='Alice', lastname='Apricot', is_active=True, is_staff=True, is_superuser=False)
Keyword only:
>>> User(firstname='Alice', lastname='Apricot', is_active=True, is_staff=True, is_superuser=False)
User(firstname='Alice', lastname='Apricot', is_active=True, is_staff=True, is_superuser=False)
4.4.5. Following Fields
Since Python 3.10
from dataclasses import KW_ONLY
Any fields after a pseudo-field with the type of KW_ONLY are required
as keyword-only fields. Note that a pseudo-field of type KW_ONLY is
otherwise completely ignored. This includes the name of such a field.
By convention, a name of _ is used for a KW_ONLY field.
SetUp:
>>> from dataclasses import KW_ONLY
Definition:
>>> @dataclass
... class User:
... firstname: str
... lastname: str
... _: KW_ONLY
... is_active: bool
... is_staff: bool
... is_superuser: bool
Positional only:
>>> User('Alice', 'Apricot', True, True, False)
Traceback (most recent call last):
TypeError: User.__init__() takes 3 positional arguments but 6 were given
Mixed:
>>> User('Alice', 'Apricot', is_active=True, is_staff=True, is_superuser=False)
User(firstname='Alice', lastname='Apricot', is_active=True, is_staff=True, is_superuser=False)
Keyword only:
>>> User(firstname='Alice', lastname='Apricot', is_active=True, is_staff=True, is_superuser=False)
User(firstname='Alice', lastname='Apricot', is_active=True, is_staff=True, is_superuser=False)