On Thu, Jun 24, 2021 at 1:03 AM Ralf Gommers <ralf.gommers@gmail.com> wrote:
I agree with this. Enums are nice _in theory_, but once you start using them you quickly figure out they're clunky, plus the all-caps looks bad (I'd consider ignoring that style recommendation). For API design they don't make all that much sense compared to "here's a list of strings we accept, and everything else raises an informative error". The only reasons I can think of to use them are:

1. Cases like never-copy, when there's a reason to have an object we can add a method too (`__bool__` here)
2. There's a long list of options and we want to give users  a way to explore or iterate over those, so a public object is useful. so cases where we'd otherwise use a class (instance) instead of documenting the string options. I can't think of many examples like this, padding modes for `scipy.ndimage.convolve` is the only one that comes to mind.

I think Enums are a very clean abstraction for capturing a discrete set of options in a type-safe way, both at runtime and with static checks. You also don't have to keep lists of strings in sync, which makes them a little easier to document.

That said, I agree that in most cases the overall benefits are rather marginal. I don't think it's worth a mass migration of existing NumPy functions, which uses strings for categorical options.

In this particular case, I think there is a clear advantage to using an enum, to avoid inadvertent bugs with old versions of NumPy.
In general I don't expect we'd need (m)any more. Hence I'd suggest adding a new namespace like `np.flags` is not a good idea. Right now all we need is a single object, if we end up going the enum route.

For this one, I'd say it kinda looks like we do need one, so then  let's just add one and be done with it, rather than inventing odd patterns like tacking enum members onto an existing function.
I agree with both of these. If we're only going to add a couple of enums, it's not worth worrying about a couple of extra objects polluting NumPy's namespace. I would just add np.CopyMode, rather than inventing a new design pattern.

At some point in the future, we might either:
(1) switch the interface to use strings, in which case we would stop recommending/documenting CopyMode (like plenty of other top level objects in the NumPy namespace)
(2) add many more enums, in which case we can consider assigning enums as function attributes or putting them in a namespace. But so far the only other enum I've heard suggested is np.ClipMode. Adding two enums to the NumPy namespace would hardly make a difference at this point, given how many objects are already there.