4.7. Dataclass Field
default
- Default value for the fielddefault_factory
- Field factoryinit
- Use this field in__init__()
repr
- Use this field in__repr__()
hash
- Use this field in__hash__()
compare
- Use this field in comparison functions (le, lt, gt, ge, eq, ne)metadata
- For storing extra information about fieldkw_only
- field will become a keyword-only parameter to__init__()
def field(*,
default: Any,
default_factory: Any,
init: bool = True,
repr: bool = True,
hash: bool = None,
compare: bool = True,
metadata: dict[str,Any] = None,
kw_only: bool) -> None
4.7.1. SetUp
>>> from dataclasses import dataclass, field
>>> from typing import ClassVar
4.7.2. Default
default
- Default value for the field
>>> @dataclass
... class User:
... firstname: str
... lastname: str
... role: str = field(default='user')
>>> User('Mark', 'Watney')
User(firstname='Mark', lastname='Watney', role='user')
>>> User('Mark', 'Watney', role='admin')
User(firstname='Mark', lastname='Watney', role='admin')
Note, that this is equal to:
>>> @dataclass
... class User:
... firstname: str
... lastname: str
... role: str = 'user'
4.7.3. Default Factory
default_factory
- Field factory
The following code will not work:
>>> @dataclass
... class User:
... firstname: str
... lastname: str
... groups: list[str] = ['users', 'staff', 'admins']
Traceback (most recent call last):
ValueError: mutable default <class 'list'> for field groups is not allowed: use default_factory
If you want to create a list with default values, you have to create a field
with default_factory=lambda: ['users', 'staff', 'admins']
. Lambda
expression will be evaluated on field initialization.
>>> @dataclass
... class User:
... firstname: str
... lastname: str
... groups: list[str] = field(default_factory=lambda: ['users', 'staff', 'admins'])
>>> User('Mark', 'Watney')
User(firstname='Mark', lastname='Watney', groups=['users', 'staff', 'admins'])
4.7.4. Init
>>> @dataclass
... class User:
... firstname: str
... lastname: str
... role: str = field(default='user', init=False)
>>> User('Mark', 'Watney')
User(firstname='Mark', lastname='Watney', role='user')
>>> User('Mark', 'Watney', role='admin')
Traceback (most recent call last):
TypeError: User.__init__() got an unexpected keyword argument 'role'
4.7.5. Repr
>>> @dataclass
... class User:
... firstname: str
... lastname: str
... role: str = field(repr=False)
>>> User('Mark', 'Watney', role='admin')
User(firstname='Mark', lastname='Watney')
4.7.6. kw_only
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
... role: str = field(kw_only=True)
>>> User('Mark', 'Watney', role='admin')
User(firstname='Mark', lastname='Watney', role='admin')
>>> User('Mark', 'Watney', 'admin')
Traceback (most recent call last):
TypeError: User.__init__() takes 3 positional arguments but 4 were given
4.7.7. Use Case - 1
Validation
>>> from typing import ClassVar, Self
>>> from dataclasses import dataclass, field
>>> from datetime import time, datetime, timezone
>>>
>>>
>>> @dataclass
... class Group:
... gid: int
... name: str
>>>
>>> @dataclass(frozen=True)
... class User:
... firstname: str
... lastname: str
... roles: list[str] = field(default_factory=lambda: ['users', 'staff', 'admins'])
... friends: list[Self] = field(default_factory=list, kw_only=True)
... groups: list[Group] = field(default_factory=list, kw_only=True)
... account_created: datetime = field(default_factory=lambda: datetime.now(tz=timezone.utc), kw_only=True)
... permissions: list[dict] = field(default_factory=dict, kw_only=True)