Repository: scikit-learn/scikit-learn
File: sklearn/inspection/_plot/decision_boundary.py (Python)

Code before:
    """

    if multiclass_colors is None:
        multiclass_colors = "tab10" if n_classes <= 10 else "gist_rainbow"

    if isinstance(multiclass_colors, str):
        if multiclass_colors not in mpl.pyplot.colormaps():
            raise ValueError(
                "When 'multiclass_colors' is a string, it must be a valid "
                f"Matplotlib colormap. Got: {multiclass_colors}"
            )
        cmap = mpl.pyplot.get_cmap(multiclass_colors)
        if cmap.N < n_classes:
            raise ValueError(
                f"Colormap '{multiclass_colors}' only has {cmap.N} colors, but "
                f"{n_classes} classes are to be displayed. Please specify a "
                "different colormap or provide a list of colors via "
                "'multiclass_colors'."
            )
        if cmap.N < 256:
            # Special case for the qualitative colormaps that encode a
            # discrete set of colors that are easily distinguishable, contrary to other
            # colormaps that are continuous (for which `cmap.N` >= 256).
            return mpl.colors.to_rgba_array(cmap.colors[:n_classes])
        else:
            return cmap(np.linspace(0, 1, n_classes))

    elif isinstance(multiclass_colors, list):
        if len(multiclass_colors) != n_classes:
            raise ValueError(
                "When 'multiclass_colors' is a list, it must be of the same "
                f"length as the classes or labels to plot ({n_classes}), got: "
                f"{len(multiclass_colors)}."
            )
        elif any(not mpl.colors.is_color_like(col) for col in multiclass_colors):
            raise ValueError(
                "When 'multiclass_colors' is a list, it can only contain valid"
                f" Matplotlib color names. Got: {multiclass_colors}"
            )
        return [mpl.colors.to_rgba(color) for color in multiclass_colors]

    else:
        raise ValueError("'multiclass_colors' must be a list or a str.")


class DecisionBoundaryDisplay:
    """Decisions boundary visualization.

    It is recommended to use
    :func:`~sklearn.inspection.DecisionBoundaryDisplay.from_estimator`
    to create a :class:`DecisionBoundaryDisplay`. All parameters are stored as

Review comment (suggestion):
This is a simplification of 
```
cmap = plt.get_cmap(cmap, n_classes)
colors = cmap(np.linspace(0, 1, n_classes))
````
which we had before.
In the old version, we first sample `n_classes` "discrete" colors, and then select `n_classes` evenly spaced classes from the colormap, which is a bit redundant. The results are almost the same (not distinguishable in a visual comparison: 
<img width="1211" height="811" alt="Image" src="https://github.com/user-attachments/assets/e4b886fe-7525-45b6-9283-b1471ef70cf1" />
but too different for `assert_allclose` to pass, so I also had to adapt the test accordingly.)

I also simplified the color selection to two cases, based on the colormap size (all current qualitative colormaps have at most 20 colors, for all others `.N` is at least 256), so that all non-qualitative colormaps are handled the same way (even though some, like "viridis", but for example not "gist_rainbow", also have a `colors` attribute).

Code after:
    """

    if multiclass_colors is None:
        multiclass_colors = "tab10" if n_classes <= 10 else "gist_rainbow"

    if isinstance(multiclass_colors, str):
        if multiclass_colors not in mpl.pyplot.colormaps():
            raise ValueError(
                "When 'multiclass_colors' is a string, it must be a valid "
                f"Matplotlib colormap. Got: {multiclass_colors}"
            )
        cmap = mpl.pyplot.get_cmap(multiclass_colors)
        if cmap.N < n_classes:
            raise ValueError(
                f"Colormap '{multiclass_colors}' only has {cmap.N} colors, but "
                f"{n_classes} classes are to be displayed. Please specify a "
                "different colormap or provide a list of colors via "
                "'multiclass_colors'."
            )
        if cmap.N < 256:
            # Special case for the qualitative colormaps that encode a
            # discrete set of colors that are easily distinguishable, contrary to other
            # colormaps that are continuous (for which `cmap.N` >= 256).
            return mpl.colors.to_rgba_array(cmap.colors[:n_classes])
        else:
            return cmap(np.linspace(0, 1, n_classes))

    elif isinstance(multiclass_colors, list):
        if len(multiclass_colors) != n_classes:
            raise ValueError(
                "When 'multiclass_colors' is a list, it must be of the same "
                f"length as the classes or labels to plot ({n_classes}), got: "
                f"{len(multiclass_colors)}."
            )
        elif any(not mpl.colors.is_color_like(col) for col in multiclass_colors):
            raise ValueError(
                "When 'multiclass_colors' is a list, it can only contain valid"
                f" Matplotlib color names. Got: {multiclass_colors}"
            )
        return [mpl.colors.to_rgba(color) for color in multiclass_colors]

    else:
        raise TypeError("'multiclass_colors' must be a list or a str.")


class DecisionBoundaryDisplay:
    """Decisions boundary visualization.

    It is recommended to use
    :func:`~sklearn.inspection.DecisionBoundaryDisplay.from_estimator`
    to create a :class:`DecisionBoundaryDisplay`. All parameters are stored as