4.4. Dataclass KWonly

4.4.1. SetUp

>>> from dataclasses import dataclass, field

4.4.2. All Fields

  • Since Python 3.10

  • Mark all fields as keyword-only

  • kw_only=False by default

If true, then all fields will be marked as keyword-only. If a field is marked 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
...     height: float
...     weight: float

Usage:

>>> User(firstname='Mark', lastname='Watney', height=178.0, weight=75.5)
User(firstname='Mark', lastname='Watney', height=178.0, weight=75.5)

Errors:

>>> User('Mark', lastname='Watney', height=178.0, weight=75.5)
Traceback (most recent call last):
TypeError: User.__init__() takes 1 positional argument but 2 positional arguments (and 3 keyword-only arguments) were given
>>> User('Mark', 'Watney', height=178.0, weight=75.5)
Traceback (most recent call last):
TypeError: User.__init__() takes 1 positional argument but 3 positional arguments (and 2 keyword-only arguments) were given
>>> User('Mark', 'Watney', 178.0, weight=75.5)
Traceback (most recent call last):
TypeError: User.__init__() takes 1 positional argument but 4 positional arguments (and 1 keyword-only argument) were given
>>> User('Mark', 'Watney', 178.0, 75.5)
Traceback (most recent call last):
TypeError: User.__init__() takes 1 positional argument but 5 were given

4.4.3. Particular Field

  • Since Python 3.10

  • keyword-only

If true, this field will be marked as keyword-only. This is used when the generated __init__() method's parameters are computed.

>>> @dataclass
... class User:
...     firstname: str
...     lastname: str
...     height: float = field(kw_only=True)
...     weight: float = field(kw_only=True)

Usage:

>>> User(firstname='Mark', lastname='Watney', height=178.0, weight=75.5)
User(firstname='Mark', lastname='Watney', height=178.0, weight=75.5)
>>> User('Mark', lastname='Watney', height=178.0, weight=75.5)
User(firstname='Mark', lastname='Watney', height=178.0, weight=75.5)
>>> User('Mark', 'Watney', height=178.0, weight=75.5)
User(firstname='Mark', lastname='Watney', height=178.0, weight=75.5)

Errors:

>>> User('Mark', 'Watney', 178.0, weight=75.5)
Traceback (most recent call last):
TypeError: User.__init__() takes 3 positional arguments but 4 positional arguments (and 1 keyword-only argument) were given
>>> User('Mark', 'Watney', 178.0, 75.5)
Traceback (most recent call last):
TypeError: User.__init__() takes 3 positional arguments but 5 were given

4.4.4. Following Fields

  • Since Python 3.10

  • from dataclasses import KW_ONLY

Any fields after a pseudo-field with the type of KW_ONLY are marked 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
...     height: float
...     weight: float

Usage:

>>> User(firstname='Mark', lastname='Watney', height=178.0, weight=75.5)
User(firstname='Mark', lastname='Watney', height=178.0, weight=75.5)
>>> User('Mark', lastname='Watney', height=178.0, weight=75.5)
User(firstname='Mark', lastname='Watney', height=178.0, weight=75.5)
>>> User('Mark', 'Watney', height=178.0, weight=75.5)
User(firstname='Mark', lastname='Watney', height=178.0, weight=75.5)

Errors:

>>> User('Mark', 'Watney', 178.0, weight=75.5)
Traceback (most recent call last):
TypeError: User.__init__() takes 3 positional arguments but 4 positional arguments (and 1 keyword-only argument) were given
>>> User('Mark', 'Watney', 178.0, 75.5)
Traceback (most recent call last):
TypeError: User.__init__() takes 3 positional arguments but 5 were given