jgyou
jgyou

Reputation: 493

Difference in behavior between basic type (int) and complex type (np.ndarray)

Why are the following objects behaving differently with regard to the [x] * n operation? I.e. why does the first operation (in[94]) modify a single entry of the list, whereas the second operation (in[99]) modify all the entries?

In [91]: x = 8

In [92]: y = [x] * 10

In [93]: y
Out[93]: [8, 8, 8, 8, 8, 8, 8, 8, 8, 8]

In [94]: y[1] = 4

In [95]: y
Out[95]: [8, 4, 8, 8, 8, 8, 8, 8, 8, 8]

In [96]: x = np.zeros(shape=(3,3))

In [97]: y = [x] * 10

In [98]: y
Out[98]: 
[array([[ 0.,  0.,  0.],
        [ 0.,  0.,  0.],
        [ 0.,  0.,  0.]]), array([[ 0.,  0.,  0.],
        [ 0.,  0.,  0.],
        [ 0.,  0.,  0.]]), array([[ 0.,  0.,  0.],
        [ 0.,  0.,  0.],
        [ 0.,  0.,  0.]]), array([[ 0.,  0.,  0.],
        [ 0.,  0.,  0.],
        [ 0.,  0.,  0.]]), array([[ 0.,  0.,  0.],
        [ 0.,  0.,  0.],
        [ 0.,  0.,  0.]]), array([[ 0.,  0.,  0.],
        [ 0.,  0.,  0.],
        [ 0.,  0.,  0.]]), array([[ 0.,  0.,  0.],
        [ 0.,  0.,  0.],
        [ 0.,  0.,  0.]]), array([[ 0.,  0.,  0.],
        [ 0.,  0.,  0.],
        [ 0.,  0.,  0.]]), array([[ 0.,  0.,  0.],
        [ 0.,  0.,  0.],
        [ 0.,  0.,  0.]]), array([[ 0.,  0.,  0.],
        [ 0.,  0.,  0.],
        [ 0.,  0.,  0.]])]

In [99]: y[1][1,2] = 5

In [100]: y
Out[100]: 
[array([[ 0.,  0.,  0.],
        [ 0.,  0.,  5.],
        [ 0.,  0.,  0.]]), array([[ 0.,  0.,  0.],
        [ 0.,  0.,  5.],
        [ 0.,  0.,  0.]]), array([[ 0.,  0.,  0.],
        [ 0.,  0.,  5.],
        [ 0.,  0.,  0.]]), array([[ 0.,  0.,  0.],
        [ 0.,  0.,  5.],
        [ 0.,  0.,  0.]]), array([[ 0.,  0.,  0.],
        [ 0.,  0.,  5.],
        [ 0.,  0.,  0.]]), array([[ 0.,  0.,  0.],
        [ 0.,  0.,  5.],
        [ 0.,  0.,  0.]]), array([[ 0.,  0.,  0.],
        [ 0.,  0.,  5.],
        [ 0.,  0.,  0.]]), array([[ 0.,  0.,  0.],
        [ 0.,  0.,  5.],
        [ 0.,  0.,  0.]]), array([[ 0.,  0.,  0.],
        [ 0.,  0.,  5.],
        [ 0.,  0.,  0.]]), array([[ 0.,  0.,  0.],
        [ 0.,  0.,  5.],
        [ 0.,  0.,  0.]])]

Upvotes: 3

Views: 50

Answers (1)

Nitish
Nitish

Reputation: 7196

tl;dr : You implicitly made a shallow copy of the matrix when you were expecting a deep copy. Documentation

Consider the following bit of code:

In [38]: import numpy

In [39]: a = numpy.eye(2)

In [40]: a
Out[40]:
array([[ 1.,  0.],
       [ 0.,  1.]])

In [41]: b = a

In [42]: b
Out[42]:
array([[ 1.,  0.],
       [ 0.,  1.]])

In [43]: a[0,0] = 2

In [44]: a
Out[44]:
array([[ 2.,  0.],
       [ 0.,  1.]])

In [45]: b
Out[45]:
array([[ 2.,  0.],
       [ 0.,  1.]])

Also:

In [46]: id(a)
Out[46]: 140529107552512

In [47]: id(b)
Out[47]: 140529107552512

I defined a. Set b=a and then changed a to find the same change in b even though I didn't touch b.

By your line [x] * 10, it made 10 shallow copies of x. So, change in any one reflects on all others.

In [90]: x = np.zeros(shape=(3,3))
In [95]: y = [x] * 10

In [96]: id(y[0])
Out[96]: 140529110575952

In [97]: id(y[1])
Out[97]: 140529110575952

In [98]: y[1][1,2] = 5

In [99]: id(y[0])
Out[99]: 140529110575952

In [100]: id(y[1])
Out[100]: 140529110575952

This is not a problem for int or any other non-compound type.

In [105]: x = 0

In [106]: y = [x] * 10

In [107]: y
Out[107]: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

In [108]: y[1] = 2

In [109]: y
Out[109]: [0, 2, 0, 0, 0, 0, 0, 0, 0, 0]

In [110]: id(y[0])
Out[110]: 140529069263200

In [111]: id(y[1])
Out[111]: 140529069263152

Upvotes: 2

Related Questions