AI Skill Report Card
Using Reprlib
Quick Start14 / 15
Pythonimport reprlib # Truncated repr for large data r = reprlib.Repr() r.maxlist = 3 print(r.repr(list(range(100)))) # [0, 1, 2, ...] # Quick one-off truncated repr print(reprlib.repr(list(range(100)))) # [0, 1, 2, ...] # Protect custom repr methods from infinite recursion class Tree: def __init__(self, children=None): self.children = children or [] @reprlib.recursive_repr() def __repr__(self): return f"Tree({self.children!r})" t = Tree() t.children = [t] # self-referential print(repr(t)) # Tree([...])
Recommendation▾
Add an example showing a bad outcome, e.g., forgetting recursive_repr and hitting RecursionError, to illustrate contrast
Workflow13 / 15
Progress:
- Identify whether the need is (a) truncated repr for built-in-like containers/strings, or (b) recursion-safety for a custom
__repr__ - For (a): use
reprlib.repr()for a quick default, or subclass/configurereprlib.Reprfor custom limits - For (b): decorate
__repr__with@reprlib.recursive_repr() - Verify output length/behavior matches expectations
- Integrate into logging/debugging code where output size matters
Using reprlib.Repr for custom limits
- Instantiate
r = reprlib.Repr()(or subclass it for reusable config). - Set relevant
max*attributes before calling.repr():maxlevel— max recursion depth (default 6)maxtuple,maxlist,maxarray,maxdict,maxset,maxfrozenset,maxdeque— max elements shown per container typemaxstring— max characters shown forstrmaxlong— max digits shown forintmaxother— max chars for other objects' repr
- Call
r.repr(obj)for the general dispatcher, or type-specific methods liker.repr_list(obj, level)directly. - To customize behavior for a specific type, subclass
Reprand overriderepr_<typename>(self, obj, level).
Using recursive_repr decorator
- Import
reprlib.recursive_repr. - Apply as a decorator directly above
__repr__(must decorate__repr__specifically, or any method returning a string representation). - Optionally pass a fill-in string:
@reprlib.recursive_repr(fillvalue='...')(default is'...'). - When a recursive call to the same object's
__repr__is detected (via a thread-local set of ids), the decorator returns the fill-in value instead of recursing infinitely.
Recommendation▾
Include guidance on performance/overhead considerations when using Repr in hot logging paths
Examples17 / 20
Example 1: Truncated list repr Input:
Pythonreprlib.repr(list(range(1000)))
Output:
Python'[0, 1, 2, 3, 4, 5, 6, ...]'
Example 2: Custom Repr subclass Input:
Pythonclass MyRepr(reprlib.Repr): def __init__(self): super().__init__() self.maxstring = 10 self.maxlist = 2 aRepr = MyRepr() aRepr.repr(["hello world this is long", "b", "c", "d"])
Output:
Python"['hello wor...', 'b', ...]"
Example 3: Recursive structure protection Input:
Pythonclass Node: def __init__(self): self.next = None @reprlib.recursive_repr() def __repr__(self): return f"Node(next={self.next!r})" n = Node() n.next = n repr(n)
Output:
Python'Node(next=...)'
Example 4: Nested container truncation with maxlevel Input:
Pythonr = reprlib.Repr() r.maxlevel = 2 r.repr([1, [2, [3, [4, [5]]]]])
Output:
Python'[1, [2, [...]]]'
Recommendation▾
Mention interaction with dataclasses or attrs which auto-generate __repr__, since decorating them requires care
Best Practices
- Use the module-level
reprlib.repr()for quick, one-off truncation with sensible defaults — no need to instantiateReprfor simple cases. - Instantiate and configure a
Reprobject (or subclass) once and reuse it when truncation settings need to be consistent across many calls (e.g., in a logging utility). - Always apply
@reprlib.recursive_repr()to__repr__methods of classes that can form cycles or self-references (trees, graphs, linked structures, or containers that may hold themselves). - Prefer subclassing
Reprand overridingrepr_<type>methods when default truncation for a specific type isn't sufficient, rather than writing truncation logic manually. - Remember
reprlib.repr()is meant for display/debug purposes — the output is not necessarily valid Python that can beeval()'d back into the original object once truncated.
Common Pitfalls
- Don't confuse
reprlib.Repr.maxlevelbehavior — it counts down levels, and nested containers beyond the limit collapse to..., not to an empty container. - Don't apply
@reprlib.recursive_repr()to methods other than the string-producing repr method — it's specifically designed to guard against recursive string conversion, using a thread-local + id-based guard. - Don't expect
reprlib.repr()truncated output to be safe foreval(); it's for human-readable debugging only. - Don't forget that
maxstringandmaxlongapply per-value, not per-container — a container of many short strings can still produce a long overall output ifmaxlist/maxdictetc. are large. - Don't manually implement recursion guards with global mutable state when
reprlib.recursive_repr()already handles thread-safety via thread-local storage.