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=False
by 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)