One funny thing, it's only in the Python world that C is a defined speed. When we implement libraries in actual C, C++, Rust etc, we benchmark and compare different libraries, they can have wildly different performance - depending on you know, work put into them. But Python is just a two-speed world: Python or C ;-)
Like this standard usage which misuses all the operators:
a = b[c == 1]
One would think that would be equivalent to b[true] or false, and what's that supoosed to mean? But if c is a numpy array it's instead doing element wise comparison on c, and the new array of booleans will be used to index into b. If you don't know this, it's impossible to figure out looking at the code. Too many footguns imo. Same with pytorch, broadcasting is nice, but makes it hard to figure out what's going to happen in practice with the shapes being calculated upon.A more weird but still basic example from pandas is the way it handles indexing and the confusion between .loc, .iloc, .ix, .at and plain '[]'. That part of the API should be really basic but for some reason it's a giant mess.
I feel Notebooks aren't used as much because they're a great tool, but that they are used so much as a necessity since you need to look at live data to have any hopes of understanding what's going on. Why couldn't a compiler instead tell me what I'm trying to do will fail?
Last year, I had an in-person discussion with a numpy core developer in which I proposed adding pandas-like syntax to numpy, e.g. allowing the author to use:
a.boolmask[b == c]
(but maybe not so verbose).
A problem immediately arises: An array can have multiple axes, and each could be indexed with a different type within the same slicing call.
One idea might be to allow the author to explicitly wrap the arguments with some dummy class to make clear what types they’re using:
a[np.boolmask(b == c), d, np.intlist(e)]
(Again, perhaps choosing shorter names in practice.)
The idea would be that the wrapper merely “looks like” the thing it wraps, but contains an assertion to verify the type of the argument.
Anyway, I agree that notebooks (or REPLs in general) are great for verifying your assumptions about how little snippets will behave. But I think they would be useful even in a fully statically-typed compiled language, too.
The array syntax is not what you expect if you're coming from a background primarily in programming applications using other dynamically-typed languages or even Python itself, but it's exactly what you'd expect if you're a scientist used to using MATLAB, or even just used to doing math on paper. And at least back in the early days, that was how hedge funds and quantitative finance worked. They weren't looking for application programmers. They were looking for physicists and electrical engineers. It was a lot easier to teach them how to program than to teach programmers about Brownian motion and stochastic processes.
For their intended use cases, Numpy and pandas are among the greatest tools ever created, honestly comparable to MATLAB itself except also free.
What you've shown here is pandas 101. If it is confusing, it's a sign you need to understand the underlying basics of NumPy and pandas.