Return link to subpattern from function in numpy

>>> a = np.arange(9).reshape((3, 3)) >>> a array([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) >>> def sub(a): ... return a[:2, :2] ... >>> sub(a) array([[0, 1], [3, 4]]) >>> sub(a) = np.arange(4).reshape((2, 2)) File "<stdin>", line 1 SyntaxError: cant assign to function call >>> t = a[:2, :2] >>> t = np.arange(4).reshape((2, 2)) >>> a array([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) >>> a[:2, :2] = np.arange(4).reshape((2, 2)) >>> a array([[0, 1, 2], [2, 3, 5], [6, 7, 8]]) 

And it's pretty obvious why this happens: when I type t = .. , I just 'relink' t for other data in memory. But there are questions:

  • How can I hack this and pass a link to a submatrix from a function? and
  • can still change the values โ€‹โ€‹of the submatrix?
+5
source share
2 answers
  • how can i ... pass a link to a submatrix from a function?

Simply put, you cannot return an l-value from a function call in Python, as in C ++. In your case, Python assumes that you assign the value directly to sub(a) , which is a function call, not the object it returns.

You can use indexing to get a reference to the source object, as described below. This will allow you to change part of the original matrix.

  1. and still be able to change the values โ€‹โ€‹of the submatrices?

You can change the values โ€‹โ€‹of the submatrix of the array inside the function itself, for example:

 def sub(a): a[:2, :2] = np.arange(4).reshape((2,2)) return a[:2, :2] 

This will not only return modified submatrix, but it will also change the array itself.


Objects are passed by reference, but their links are passed by value:

Like Java, Python has a pass-by-value, so all objects are passed as references to a function, and these links are passed by value.

Therefore, when you index this array object and change its value inside the function, you change the value of the location in memory pointed to by this link, but if you change the link itself, it will not change the original object because its link was transmitted only by value.

Use indexing to pass an object reference by value:

Following this explanation, you can go further and return a reference to the object from the function by value and change the matrix using it outside the function:

  • Call the sub(a) function, which will return a reference by value to a submatrix, which itself is a reference to the original matrix passed by value.
  • Assign this function call to another variable that will pass a submatrix reference by the value of this new variable, x = sub(a)
  • Index this x[:] = np.ones((2,2)) to select all its contents and change their value: x[:] = np.ones((2,2))
  • This will also change the original matrix a , because you changed the value of the location in memory that x accessing.

     >>> x = sub(a) >>> x[:] = np.ones((2,2)) >>> x array([[1, 1], [1, 1]]) >>> a array([[1, 1, 2], [1, 1, 5], [6, 7, 8]]) 

    OR, as a shortcut:

     >>> sub(a)[:] = np.ones((2,2)) >>> a array([[1, 1, 2], [1, 1, 5], [6, 7, 8]]) 

Changing the link does not change the object:

  1. However, now if you set the variable x to np.ones((2,2)) , then a will not change, because in doing so you change the link itself, which was passed by value.

     >>> x = 2 # this won't change a because x is a reference passed by value >>> a array([[1, 1, 2], [1, 1, 5], [6, 7, 8]]) 
+1
source

The correct action in Python :

 In [97]: t=sub(a) In [98]: t Out[98]: array([[0, 1], [3, 4]]) In [100]: t[:]=np.arange(4).reshape(2,2) In [101]: t Out[101]: array([[0, 1], [2, 3]]) In [102]: a Out[102]: array([[0, 1, 2], [2, 3, 5], [6, 7, 8]]) 

The function returns the view original array, the same as t = a[:2, :2] outside the function. t=... reassigns the variable, but t[:]=... changes the contents (array elements) of the view. And since this is a view, the original contents of the array also change. This is the same as your a[:2, :2] =...

As long as you use [:] , you do not need to assign an intermediate variable:

 In [104]: sub(a)[:]=np.zeros((2,2)) In [105]: a Out[105]: array([[0, 0, 2], [0, 0, 5], [6, 7, 8]]) 
0
source

Source: https://habr.com/ru/post/1202389/


All Articles