Chiel
Chiel

Reputation: 6194

Using a numpy view to a non-existing array

After defining an arrray a with zeros, I can create a view to the leftmost column with the following function:

a = np.zeros((5, 5))
a_left_col = a[:, 0]

a_left_col[:] = 2.

which prints for a:

array([[2., 0., 0., 0., 0.],
       [2., 0., 0., 0., 0.],
       [2., 0., 0., 0., 0.],
       [2., 0., 0., 0., 0.],
       [2., 0., 0., 0., 0.]])

If I subsequently reinitialize a with

a = np.zeros((5, 5))

then the view still exists, but it refers to nothing anymore. How does Python handle the situation if I do a_left_col[:] = 2 again? Is this undefined behavior like in C or C++, or does Python handle it properly, and if so, why doesn't it throw an error?

Upvotes: 1

Views: 32

Answers (2)

MB-F
MB-F

Reputation: 23647

The original object still exists because it is referenced by the view. (Although it can be no longer accessed through variable a.)

Let's have a detailed look at the object's reference counts:

import sys
import numpy as np

a = np.zeros((5, 5))
print(sys.getrefcount(a))  # 2

a_left_col = a[:, 0]
print(sys.getrefcount(a))  # 3
print(sys.getrefcount(a_left_col.base))  # 3
print(a_left_col.base is a)  # True

a = np.ones((5, 5))
print(sys.getrefcount(a_left_col.base))  # 2

Note that a_left_col.base is the reference to the original array. When we reassing a The reference count on the object decreases but it still exists because it is reachable throgh a_left_col.

Upvotes: 1

Demosthenes
Demosthenes

Reputation: 1535

Behaviour is not undefined. You are merely creating a new object a. The old one is not deallocated, but still exists in memory, since a_left_col still references it. Once you reinitialize a_left_col, the original array can be deallocated.

Upvotes: 1

Related Questions