From 57188341a66f8b385fd200d6e478b35ce6da6d7d Mon Sep 17 00:00:00 2001 From: jbranchaud Date: Sun, 26 Jul 2026 19:11:39 -0500 Subject: [PATCH] Add Configure Other Attributes Of Dataclass Field as a Python TIL --- README.md | 3 +- ...ure-other-attributes-of-dataclass-field.md | 63 +++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 python/configure-other-attributes-of-dataclass-field.md diff --git a/README.md b/README.md index e3f6cbe..3d35971 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ working across different projects via [VisualMode](https://www.visualmode.dev/). For a steady stream of TILs, [sign up for my newsletter](https://visualmode.kit.com/newsletter). -_1839 TILs and counting..._ +_1840 TILs and counting..._ See some of the other learning resources I work on: @@ -1079,6 +1079,7 @@ If you've learned something here, support my efforts writing daily TILs by - [Check If Package Is Installed With Pip](python/check-if-package-is-installed-with-pip.md) - [Check Precondition Before Click Arg Parsing](python/check-precondition-before-click-arg-parsing.md) - [Commit Writes From Executed SQLite Statements](python/commit-writes-from-executed-sqlite-statements.md) +- [Configure Other Attributes Of Dataclass Field](python/configure-other-attributes-of-dataclass-field.md) - [Control Passing Of Time In Tests](python/control-passing-of-time-in-tests.md) - [Create A Dummy DataFrame In Pandas](python/create-a-dummy-dataframe-in-pandas.md) - [Create A Range Of Descending Values](python/create-a-range-of-descending-values.md) diff --git a/python/configure-other-attributes-of-dataclass-field.md b/python/configure-other-attributes-of-dataclass-field.md new file mode 100644 index 0000000..44ce8ed --- /dev/null +++ b/python/configure-other-attributes-of-dataclass-field.md @@ -0,0 +1,63 @@ +# Configure Other Attributes Of Dataclass Field + +I have a basic [`dataclass`](https://docs.python.org/3/library/dataclasses.html) +defined with a few fields that looks like this: + +```python +from dataclasses import dataclass +from datetime import datetime + +@dataclass +class Session: + start_time: datetime + project_name: str + tags: list[str] + end_time: datetime | None = None + + # ... + +new_session = Session(start_time, "my-project", []) +``` + +This syntax lets me define the fields that make up arguments to the underlying +`__init__` function. This only gets me so far though. What if I want `tags` to +have a default value of `[]`? What if I want to force those optional fields +(`tags` and `end_time`) to be keyword-only arguments? + +To take the field definitions of my `dataclass` a bit further, I need the +[`field` function](https://docs.python.org/3/library/dataclasses.html#dataclasses.field) +which lets me configure more aspects of each field. + +```python +from dataclasses import dataclass, field +from datetime import datetime + +@dataclass +class Session: + start_time: datetime + project_name: str + tags: list[str] = field(default_factory=list, kw_only=True) + end_time: datetime | None = field(default=None, kw_only=True) + + # ... + +sesh1 = Session(start1, "my-project", tags=["pytorch", "numpy"]) +sesh2 = Session(start2, "other-project", end_time=datetime.now()) +``` + +If I were to say the default value of `tags` is simply a `[]`, then the +`dataclass` definition gets evaluated with a reference to that specific instance +of an empty list. Every new `Session` I create would share and mutate that same +list. For this reason, `dataclass` detects and warns you away from that. + +Instead, I specify `list` as the `default_factory` for `tags`. Each new +`Session` where `tags` is not provided will be factory'd a new empty list. + +For scalar values, like `None`, I can use the `default` parameter instead like +I've done for `end_time`. + +As for marking certain fields as keyword-only, the `kw_only` parameter can be +overridden with `True`. + +See [the docs for `field`](https://docs.python.org/3/library/dataclasses.html#dataclasses.field) +for all the other configurable options.