On Thu, Mar 12, 2020 at 5:50 AM Marco Sulla via Python-ideas <python-ideas@python.org> wrote:
Actually, this is the behaviour of ndarray with any dtype. And IMHO
ithis is quite.... terrible?

I can see how you would think that. But the fact is that element-wise operations are very important to numpy.

I was so used to have False for an empty iterable

I hate to be pedantic, but it doesn't work for iterables anyway:

In [2]: def iterable():
   ...:     for i in range(2):
   ...:         yield i
   ...:                                                                        

In [3]: it = iterable()                                                        

In [4]: bool(it)                                                                
Out[4]: True

In [5]: next(it)                                                                
Out[5]: 0

In [6]: next(it)                                                                
Out[6]: 1

In [7]: next(it)                                                                
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-7-bc1ab118995a> in <module>
----> 1 next(it)

StopIteration:

In [8]: bool(it)                                                                
Out[8]: True

And I don't think it could -- the only way to tell if a iterable is empty (really, exhausted) is to call next on it, and then you will have changed its state.

It does work for most sequences, however.

Honestly though, I've always been uncomfortable with the whole "truthiness" thing. I understand that in most cases, a empty sequence is logically Falsey, but the fact is that depending on the context other "Falsey" values, like 0 for intetrgers, may be perfectly reasonable. I do, in fact, often use:

if not a_sequence:
    do_something_special

but If I really want to know if a sequence is empty, maybe if len(sequence) == 0: is really a more clear test.

And as the above demonstrates, if you get an non-sequence iterable, then len() test will raise, which is much better than it always returning True.

in contrast, a numpy array will raise if you explicitly (or implicitly) call bool() on it, whereas the len() test will work as expected. And that is much safer behavior: much better to raise than pass silently with an incorrect result. And the fact is that numpy arrays will not replace an arbitrary sequence in many contexts -- at least in this case, you get an Exception the very first time to try to use one that way.

And by the way, numpy arrays are not Sequences as far as collections.abc is concerned:

isinstance(arr, collections.abc.Sequence)

A new point: maybe the default behavior for non-sequence iterables (like generators) should be to raise on a bool() call?

Note: that is NOT well thought out, it seems the default for any object is for bool(an_object) to return True -- there may well be good reason for that.

-CHB