Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange behavior in np.ndarray` "is"

Tags:

python

numpy

"is" built-in operator shows a strange behavior for the element in np.ndarray.

Although the id of the rhs and the lhs is the same, the "is" operator returns False (this behavior is specific to np.ndarray).

a = np.array([1.,])
b = a.view()
print(id(a[0] == id(b[0])))  # True
print(a[0] is b[0])  # False

This strange behavior even happens without the copy of view.

a = np.array([1.,])
print(a[0] is a[0])  # False

Does anyone know the mechanism of this strange behavior (and possibly the evidence or specification)?

Post Script: Please re-think the two examples.

  1. If this is a list, this phenomenon is not observed.
a = [0., 1., 2.,]
b = []
b.append(a[0])
print(a[0] is b[0])  # True
  1. a[0] and b[0] refer the exact same object.
a = np.array([1.,])
b = a.view()
b[0] = 0.
print(a[0])  # 0.0
print(id(a[0]) == id(b[0]))  # True

Note: This question can be a duplication, but I'm still a bit confused.

a = np.array([1.,])
b = a.view()
x = a[0]
y = b[0]
print(id(a[0]))  # 139746064667728
print(id(b[0]))  # 139746064667728
print(id(a[0]) == id(b[0])) # True
print(id(a[0]) == id(x)) # False
print(id(x) == id(y))  # False
  1. Is a[0] a temporal object?
  2. Is the id for a temporal object reused?
  3. Doesn't it contradict to the specification? (https://docs.python.org/3.7/reference/expressions.html#is)
6.10.3. Identity comparisons
The operators is and is not test for object identity: x is y is true if and only if x and y are the same object. Object identity is determined using the id() function. x is not y yields the inverse truth value.
  1. If the id is re-used for the temporal objects, why in this case the id is different?
>>> id(100000000000000000 + 1) == id(100000000000000001)
True
>>> id(100000000000000000 + 1) == id(100000000000000000)
False
like image 965
Yuki Hashimoto Avatar asked May 13 '26 16:05

Yuki Hashimoto


1 Answers

This is simply due to the difference in how the is and == works , the is operator doesn't compare the values they simply check if the two operands refer to the same object or not.

For example if you do:

print(a is a)

The output will be: True for more information look up here

When python compares it allocates different positions to the operands and the same behaviour can be observed with a simple test using an id function.

print(id(a[0]),a[0] is a[0],id(a[0]))

The output will be:

140296834593128 False 140296834593248

The answer to the question that you are asking in addition that why lists don't behave the way numpy arrays behave is simply based on their construction. Np.arrays were designed to be more efficient in their processing capabilities and more efficient in their storage than a normal python list.

So every-time you load or perform an operation on a numpy array it is loaded and assigned a different id as you can observe from the following code:

a = np.array([0., 1., 2.,])
b = []
b.append(a[0])
print(id(a[0]),a[0] is b[0],id(b[0]))

Here are the outputs of multiple re-runs of the same code in jupyter-lab:

140296834595096 False 140296834594496
140296834595120 False 140296834594496
140296834595120 False 140296834594496
140296834595216 False 140296834594496
140296834595288 False 140296834594496

Notice something strange?, The ids of the numpy array with each re-run is different however the id for the list object remains the same. This explains the strange behaviour for numpy arrays in your question.

If you want to read more on this behaviour I will suggest numpy docs

like image 166
Inder Avatar answered May 16 '26 05:05

Inder