Skip to content

Custom Types

The __lectrace__ protocol

Any class can control how it appears in the variable panel by implementing a __lectrace__ method. Return any JSON-serializable value — a dict, list, string, or number — and lectrace will display that instead of the default representation.

class Node:
    def __init__(self, val, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

    def __lectrace__(self):
        return {
            "val": self.val,
            "left": self.left.val if self.left else None,
            "right": self.right.val if self.right else None,
        }

Without __lectrace__, a Node would show as Node(val=5, left=<Node>, right=<Node>). With it, the panel shows a clean dict that students can read at a glance.


Built-in type rendering

lectrace renders these types automatically without any __lectrace__:

Type How it renders
None, bool, int, float, str Direct value
complex {"real": ..., "imag": ...}
list, tuple Indexed array
dict Key-value pairs
set, frozenset Sorted array
datetime.datetime ISO 8601 string
pathlib.Path String path
dataclasses.dataclass Dict of field names → values
numpy.ndarray Shape, dtype, and nested values
torch.Tensor Shape, dtype, and nested values
sympy.Basic String expression or numeric value

Dataclasses

Standard @dataclass classes are rendered automatically — all fields are shown as a dict:

@dataclasses.dataclass
class Point:
    x: float
    y: float

p = Point(1.5, 2.0)  # @inspect p
# shows: {"x": 1.5, "y": 2.0}

If you want a different representation — for example, only some fields, or a computed value — add __lectrace__:

@dataclasses.dataclass
class Matrix:
    data: list[list[float]]

    def __lectrace__(self):
        rows = len(self.data)
        cols = len(self.data[0]) if self.data else 0
        return {"shape": f"{rows}×{cols}", "data": self.data}

NumPy arrays

Numpy is an optional dependency. If it is installed, arrays are rendered with their shape, dtype, and values:

import numpy as np

a = np.array([[1, 2], [3, 4]])  # @inspect a
# shows: shape=[2,2], dtype=int64, values=[[1,2],[3,4]]

No import required in your lecture — lectrace detects the type lazily.


PyTorch tensors

Same as numpy — detected and rendered automatically if torch is installed:

import torch

w = torch.randn(3, 4)  # @inspect w
# shows: shape=[3,4], dtype=torch.float32, values=[...]

Depth limit

Rendering stops at depth 12. Very deeply nested structures show [depth limit] at the truncation point. Use __lectrace__ to flatten deeply nested objects before they reach that limit.