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:
- 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)?
- Why don't we get the same type result when evaluating this inside of an f-string?
- 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.
When you perform
np.empty(0) == ..., if the...is an iterable, then it will do an elementwise comparison. Sincenp.empty(0)is empty, there isn't anything to compare, so it produces an emptynp.ndarraywithbooldatatype. It doesn't returnTrue/Falsebecause 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.emptyin your "internal" version. Fix that typo and the results will be the same.