вернуть ссылку на подматрицу из функции в 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]]) 

И это довольно очевидно, почему это происходит так: когда я набираю t = .. , я просто переписываю другие данные в памяти. Но вопросы:

  1. как я могу взломать это и передать ссылку на подматрицу из функции? а также
  2. все еще можно изменить значения этого подматрица?

  1. как я могу … передать ссылку на подматрицу из функции?

Проще говоря, вы не можете вернуть l-значение из вызова функции в Python, как вы можете на C ++. В вашем случае Python предполагает, что вы назначаете значение непосредственно sub(a) , которое является вызовом функции, а не возвращенному им объекту.

Вы можете использовать индексирование, чтобы получить ссылку на исходный объект, как описано ниже. Это позволит вам изменить часть исходной матрицы.

  1. и все еще быть в состоянии изменить эти значения подматриц?

Вы можете изменить значения подматрицы массива внутри самой функции, например:

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

Это не только return измененную подматрицу, но также изменит сам массив.


Объекты Pass-by-Reference, но их ссылки: Pass-by-Value:

Как и Java, Python является передачей по значению, поэтому все объекты передаются в качестве ссылок в функцию, и эти ссылки передаются по значению.

Поэтому, когда вы индексируете этот объект массива и изменяете его значение внутри функции, вы изменяете значение местоположения в памяти, на которое ссылается эта ссылка, но если вы измените саму ссылку, то она не будет изменять исходный объект, поскольку его ссылка был передан только по значению.

Используйте индексирование для передачи ссылки на объект по значению:

Следуя этому объяснению, вы можете пойти дальше и вернуть ссылку объекта из функции по значению и изменить матрицу, используя ее вне функции:

  1. Вызовите функцию sub(a) , которая вернет ссылку по значению в подматрицу, которая сама по себе является ссылкой на исходную матрицу, переданную по значению.
  2. Назначьте этот вызов функции другой переменной, которая передаст ссылку на подматрицу по значению этой новой переменной x = sub(a)
  3. Индексируйте эту подматрицу, чтобы выбрать все ее содержимое и изменить их значение: x[:] = np.ones((2,2))
  4. Это также изменит исходную матрицу a потому что вы изменили значение местоположения в памяти, к которому относится х.

     >>> 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]]) 

    ИЛИ , в качестве ярлыка:

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

Изменение ссылки не меняет объект:

  1. Однако теперь, если вы установите переменную x в np.ones((2,2)) то a не изменится, потому что при этом вы меняете саму ссылку, которая была передана по значению.

     >>> 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]]) 

Правильное действие в 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]]) 

Функция возвращает view исходного массива, то же самое, что и для функции t = a[:2, :2] вне функции. t=... переназначает переменную, но t[:]=... изменяет содержимое (элементы массива) представления. И поскольку это представление, исходное содержимое массива также изменяется. Это то же самое, что и ваш a[:2, :2] =...

Пока вы используете [:] , вам не требуется промежуточное присвоение переменной:

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