Search code examples
pythonnumpynumpy-ndarrayf-string

Why does comparison between empty ndarrays and empty lists behave differently if done inside an f-string?


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.


Solution

  • 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.