0

I am trying to make an array, which includes the same number multiple times, but if I change it in any place, it should change everywhere. Like with lists:

a = b = [1]
>>> a.append(1)
>>> print(b)
>>> [1, 1]

So I want an array like this:

number = 10   
arr = numpy.zeros((10, 10))
arr[0][0] = number
arr[1][1] = number
arr[0][0] += 1
print(arr[1][1])

Here it should output "11". So is there a way to have multiple references to a number? I know you could replace all the 10s with 11s, but firstly this would be too inefficient, secondly this could mess things up since another number may be coincidentally a 10 too.

Thanks.

2
  • As long as the new positions are strided stepsize away, you can create views. A more representative sample (more number of places where the new number should be changed) could clarify things. Commented Sep 20, 2018 at 7:53
  • Try to use arr[0,0] style indexing on arrays. It's safer than arr[0][0]. Commented Sep 20, 2018 at 10:58

1 Answer 1

1

A zero dimensional numpy array behaves in many respects like a mutable number:

>>> import numpy as np                                                  
>>>                                                                                                                 
>>> a = 2.0            # ordinary immutable number
>>> am = np.array(2.0) # "mutable number"                                                                                          
>>>                                                                                                                 
>>> A = np.array([[a, a, am, a], [am, am, a, a]], dtype=object)
>>> A
array([[2.0, 2.0, array(2.), 2.0],                                                                                  
       [array(2.), array(2.), 2.0, 2.0]], dtype=object)

That's a bit ugly, so below I'll convert to float before printing:

>>> A.astype(float)                                                          
array([[2., 2., 2., 2.],                                                                                            
       [2., 2., 2., 2.]])

These twos are not all equal, The top left is immutable

>>> A[0, 0] += 1

Assigning to it only directly addressed cell is affected:

>>> A.astype(float)
array([[3., 2., 2., 2.],
       [2., 2., 2., 2.]])
>>> a
2.0

The third two is mutable

>>> A[0, 2] -= 1

Assigning to it all references are affected:

>>> A.astype(float)
array([[3., 2., 1., 2.],
       [1., 1., 2., 2.]])
>>> am
array(1.)

Direct assignment requires [()] syntax:

>>> A[0, 2][()] = 1.5
>>> am
array(1.5)

Otherwise the link will break:

>>> A[0, 2] = 1.8
>>> A.astype(float)
array([[3. , 2. , 1.8, 2. ],
       [1.5, 1.5, 2. , 2. ]])

Update:

In a comment OP specifies the following desired behavior:

If the mutable number am occurs k times in A, then in A * 3 the mutable number should be multiplied with 3**k, not 3.

We can get this behavior using the inplace (*=) operator and some trickery; if we want to preserve the original A, we must first make a copy:

Because numpys copying machinery normalizes our 0D arrays away, some more trickery is required to make a good copy:

>>> import copy
>>>
>>> B = np.empty_like(A)
>>> B.ravel()[...] = copy.deepcopy((*A.ravel(),))

Now do the inplace multiplication on the copy:

>>> import operator as op
>>> 
>>> C = np.frompyfunc(op.imul, 2, 1)(B, 3)
>>> 
>>> A
array([[2.0, 2.0, array(2.), 2.0],
       [array(2.), array(2.), 2.0, 2.0]], dtype=object)
>>> C
array([[6.0, 6.0, array(54.), 6.0],
       [array(54.), array(54.), 6.0, 6.0]], dtype=object)

Note that B will contain some useless hybrid data in the end and should be discarded.

>>> B
array([[2.0, 2.0, array(54.), 2.0],
       [array(54.), array(54.), 2.0, 2.0]], dtype=object)
>>> del B

Final note: this is more trickery than sane programming, so please regard it as a can-be-done rather than a should-be-done.

Sign up to request clarification or add additional context in comments.

2 Comments

This gets pretty close to what I want, but I think what I want (as described in a comment to the other answer) is impossible
@NoBody Did I hear "impossible"? Please check out the updated answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.