Customize derived behavior (How-to)¶
This page is task-focused: how to get the behavior you want when the default derive behavior doesn’t fit.
For the authoritative catalog of derives/dunders, see:
Custom string output for your type¶
Goal (custom string output)¶
Make println(f"{x}") show a friendly string.
Steps (custom string output)¶
- Define
__str__(self) -> stron yourmodel/class. - Do not also
@derive(Display)(that’s a conflict).
model User:
name: str
email: str
def __str__(self) -> str:
return f"{self.name} <{self.email}>"
Custom equality (==)¶
Goal (custom equality)¶
Compare values by a subset of fields (for example, compare by id only).
Steps (custom equality)¶
- Define
__eq__(self, other: Self) -> bool. - Do not also
@derive(Eq).
model User:
id: int
name: str
def __eq__(self, other: User) -> bool:
return self.id == other.id
Custom ordering (sorted(...))¶
Goal (custom ordering)¶
Sort values using a domain-specific rule.
Steps (custom ordering)¶
- Define
__lt__(self, other: Self) -> bool. - Do not also
@derive(Ord).
model Task:
priority: int
title: str
def __lt__(self, other: Task) -> bool:
return self.priority < other.priority
Why __lt__?
sorted(...) needs an ordering rule. Incan uses the < hook (__lt__) as the basis for ordering, so implementing
__lt__ gives the runtime a way to compare two values and sort a list.
See Derives: Comparison → Ord for the canonical ordering rules.
Custom hashing (Set / Dict keys)¶
Goal (custom hashing)¶
Use a type as a Set member / Dict key based on a custom identity.
Steps (custom hashing)¶
- Define
__hash__(self) -> int. - Ensure it matches equality: if
a == b, their hashes must match. - Do not also
@derive(Hash).
model User:
id: int
name: str
def __eq__(self, other: User) -> bool:
return self.id == other.id
def __hash__(self) -> int:
return self.id.__hash__()
Field defaults: make construction ergonomic¶
Goal (field defaults)¶
Make Type() work when fields have defaults.
Steps (field defaults)¶
- Put defaults on the fields (
field: T = expr). - Any field with no default must still be provided.
model Settings:
theme: str = "dark"
font_size: int = 14