Secrets in reprs, caches in comparisons and per-field config are common needs field() solves.
dataclasses.field() customises one field. Its parameters:
default=/default_factory=: the default value or a factory (never both).init=False: not a constructor parameter (set it in__post_init__or give a default).repr=False: hide from__repr__. Use it for passwords, tokens and huge blobs, so they don't leak into logs.compare=False: exclude from__eq__and ordering, for caches, timestamps or descriptions.hash=None|True|False: include in__hash__;None(default) followscompare.kw_only=True: keyword-only parameter (3.10+).metadata=: a read-only mapping for your own use; dataclasses ignores it. Libraries and your code read it viafields(), which is how you build per-field config such as column names, units or validation rules.
dataclasses.fields(obj_or_class) returns Field objects with .name, .type, .default and .metadata, letting you write generic code: serialisers, CSV writers, form builders.
field() must be used as a class attribute in the dataclass body; using it elsewhere has no meaning.
Example
from dataclasses import dataclass, field, fields
@dataclass
class DbConfig:
host: str = field(metadata={"env": "DB_HOST"})
port: int = field(default=5432, metadata={"env": "DB_PORT"})
password: str = field(default="", repr=False, metadata={"env": "DB_PASSWORD"})
_cache: dict = field(default_factory=dict, repr=False, compare=False)
cfg = DbConfig("db.local", password="s3cret")
print(cfg) # DbConfig(host='db.local', port=5432) (no password)
cfg._cache["x"] = 1
print(cfg == DbConfig("db.local", password="s3cret")) # True: _cache not compared
def from_env(env: dict[str, str]) -> DbConfig:
kwargs = {f.name: f.type(env[f.metadata["env"]])
for f in fields(DbConfig) if f.metadata.get("env") in env}
return DbConfig(**kwargs)
print(from_env({"DB_HOST": "prod", "DB_PORT": "6543"})) # DbConfig(host='prod', port=6543)Remember
- field(repr=False) hides secrets; compare=False excludes fields from ==
- metadata= attaches your own per-field information
- fields() lets generic code inspect names, types and metadata
Watch out for
- Printing or logging config objects whose secret fields aren't repr=False.