Batu Lab NotesPractical developer guides

Pass setup-only input through InitVar

By Batu ยท English technical notes

Also published in our Blogger archive.

InitVar represents constructor input that a dataclass needs during setup but should not retain as instance data. Greeting accepts a caller-supplied prefix, passes it to __post_init__, and uses it to calculate the stored message. Constructing Greeting("Mina", "Welcome") therefore prints Welcome, Mina!, while the persistent fields remain only name and message.

The assertions make the distinction visible. fields(greeting) excludes prefix, and because this InitVar has no class-level default, the instance does not expose a prefix attribute afterward. That is useful for transient configuration, lookup helpers, or setup context, but it is not a secrecy feature: code receiving the constructor argument can still log, retain, or otherwise expose it. It also means a later reconstruction of the object will need the setup input again if the constructor requires it.

When InitVar values exist, the generated initializer supplies them to __post_init__ in declaration order. They are pseudo-fields rather than regular dataclass fields, so they are excluded from fields() and normal dataclass field-based operations. InitVar is available with the dataclasses module, introduced in Python 3.7.

AI assistance disclosure: this article was drafted with AI assistance and should be reviewed in the context of its target Python version.

Python dataclasses documentation describes init-only variables, fields(), and how __post_init__ receives them.

from dataclasses import InitVar, dataclass, field, fields


@dataclass
class Greeting:
    name: str
    prefix: InitVar[str]
    message: str = field(init=False)

    def __post_init__(self, prefix: str) -> None:
        self.message = f"{prefix}, {self.name}!"


greeting = Greeting("Mina", "Welcome")

assert greeting.message == "Welcome, Mina!"
assert [item.name for item in fields(greeting)] == ["name", "message"]
assert not hasattr(greeting, "prefix")

print(greeting.message)
Welcome, Mina!