0

I was messing around a bit with empty ndarrays and uncovered some unexpected behavior. Minimal working example:

import numpy as np

print(f"{np.empty(0)} :: {type(np.empty(0))}")
print(f"{[]} :: {type([])}")

print(f"internal -> {np.empty(0) == []} :: {type(np.empty == [])}")

external = np.empty(0) == []
print(f"external -> {external} :: {type(external)}")

Gives the output:

[] :: <class 'numpy.ndarray'>`
[] :: <class 'list'>
internal -> [] :: <class 'bool'>
external -> [] :: <class 'numpy.ndarray'>

I have three questions about this, and I suspect that the answers are probably related:

  1. Why does numpy return an empty array instead of a boolean when comparing an empty array with an empty list (or an empty tuple, or an empty dict, or an empty set, or another instance of an empty array)?
  2. Why don't we get the same type result when evaluating this inside of an f-string?
  3. Why does numpy not return an empty array when comparing an empty array with an empty string (np.empty(0) == '' returns False)?

Based on the FutureWarning that gets raised when trying out the comparison to an empty string, I'm guessing that the answer to (1) probably has something to do with numpy performing an element-wise comparison between iterables with no elements, but I don't really get the details, nor why cases (2) and (3) seem to behave differently.

14
  • 1
    np.empty is missing the parens inside the fstring? is this intentional? Commented Feb 27, 2024 at 19:06
  • 4
    You are making two different comparisons inside your f-string. The second one doesn't compare an empty ndarray to a list, but the function np.empty itself to a empty list. That means two different __eq__ methods are involved, not that the f-string itself has anything to do with the output. Commented Feb 27, 2024 at 19:07
  • 2
    That's the string representation of an empty array, not an empty list. f'{np.empty(0)}' returns the same string. Commented Feb 27, 2024 at 19:26
  • 2
    @chrslg thanks, now I understand. It's the difference between repr and str. Commented Feb 27, 2024 at 19:31
  • 1
    @realityChemist Ah, either I completely missed that earlier, or didn't test in the two versions of NumPy I have installed. The FutureWarning is present in NumPy 1.24.2, but not 1.26.4. Commented Feb 27, 2024 at 22:46

1 Answer 1

3

When you perform np.empty(0) == ..., if the ... is an iterable, then it will do an elementwise comparison. Since np.empty(0) is empty, there isn't anything to compare, so it produces an empty np.ndarray with bool datatype. It doesn't return True/False because it would normally produce an array of boolean values, but it is empty.

Regarding the "internal"/"external" comparison, that part is a typo--you're missing the function call for np.empty in your "internal" version. Fix that typo and the results will be the same.

Sign up to request clarification or add additional context in comments.

4 Comments

Well the typo is definitely face-palm inducing, oops! Otherwise a very clear answer. I guess my only remaining question is why the behavior is different when comparing to an empty string? Instead of the ndarray it does indeed return a bool, despite strings being iterables.
(Discussion in the comments under the question has revealed that this behavior is no longer present in more recent versions of numpy, so I suppose it's essentially a moot point.)
Looking into some of the numpy source code, the typical equality method for a numpy array is only implemented for bool, int, float, or array (see here which leads to here), with scalars being cast to arrays where necessary...
... This doesn't seem to be the route taken by the np.empty(0) == "" line and I'm not sure how it works for dictionaries and sets, since those aren't listed in the supported types for promotion, so I'm not sure what mechanism leads to the boolean result here (or why dicts and sets work). Someone who knows more about numpy might be able to answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.