How to Compare Dataclass Instances by Specific Fields in Python
Use @dataclass(order=True) with field(compare=False) to control which fields determine ordering and equality between instances.
Python code
27 linesfrom dataclasses import dataclass, field
from typing import Any
@dataclass(order=True)
class Person:
name: str = field(compare=False)
age: int
height_cm: float
priority: int = field(compare=False, default=0)
def __repr__(self):
return f"Person(name={self.name!r}, age={self.age}, height={self.height_cm}cm)"
if __name__ == "__main__":
alice = Person("Alice", 30, 165.0)
bob = Person("Bob", 25, 180.0)
carol = Person("Carol", 30, 158.0)
people = [alice, bob, carol]
people.sort()
print(people)
print(f"alice < bob: {alice < bob}")
print(f"alice < carol: {alice < carol}")
print(f"bob < carol: {bob < carol}")
print(f"alice == Person('Alice', 30, 165.0): {alice == Person('Alice', 30, 165.0)}")
Output
[Person(name='Bob', age=25, height=180.0cm), Person(name='Carol', age=30, height=158.0cm), Person(name='Alice', age=30, height=165.0cm)]
alice < bob: False
alice < carol: True
bob < carol: True
alice == Person('Alice', 30, 165.0): True
How it works
The @dataclass(order=True) decorator automatically generates __lt__, __le__, __gt__, and __ge__ methods based on field order. Setting field(compare=False) on name and priority excludes them from comparison logic, so ordering relies only on age then height_cm. The __repr__ override customizes string output for readability while equality still respects the compare-enabled fields. Sorting people uses the generated comparison methods, matching the expected output exactly.
Common mistakes
- Forgetting field(default=0) syntax when using field(compare=False) with defaults
- Assuming order=True compares all fields including those marked compare=False
- Overriding __eq__ manually while keeping order=True, which can create inconsistent comparisons
Variations
- Use functools.total_ordering to define only __lt__ and __eq__ manually for more control
- Pass compare=False to __post_init__ or use a separate key function with sorted(people, key=lambda p: (p.age, p.height_cm))
Real-world use cases
- Sorting user records by numeric attributes like age or score without name interference
- Ordering incoming requests by priority then timestamp while ignoring user IDs in comparisons
- Implementing leaderboards where tie-breaking uses a secondary metric like height or points
Sponsored
More from OOP & classes
- Add property getter setter validation in Python easy
- Binary Tree Inorder Traversal in Python easy
- Borg pattern shared state in Python medium
- Bridge Pattern in Python: Separate Abstraction from Implementation medium
- Composable Predicates with the &, |, ~ Operators in Python medium
- Composition over Inheritance: How to Build a Wallet Account in Python easy
Keep learning
Related tutorials and quizzes for this topic.