назначение python в массиве против скаляра

У меня есть двумерный массив A формы (4,3) и одномерный массив a формы (4,). Я хочу поменять местами первые две строки A, а также первые два элемента в a. Я сделал следующее:

A[0,:],A[1,:] = A[1,:],A[0,:]
a[0],a[1] = a[1],a[0]

Судя по всему, это работает для a, но не работает для A. Теперь вторая строка становится первой строкой, но первая строка остается неизменной. Если я сделаю следующее:

first_row_copy = A[0,:].copy()
A[0,:] = A[1,:]
A[1,:] = first_row_copy

Тогда вроде работает. Почему не работает первый способ? (но работает для a) Кроме того, в чем разница между A_copy = A[0,:].copy() и A_copy = A[0,:]?


person Physicist    schedule 30.12.2017    source источник


Ответы (1)


numpy фрагменты — это представления базовой памяти, по умолчанию они не создают независимых копий (это оптимизация производительности/памяти). Так:

A[0,:],A[1,:] = A[1,:],A[0,:]

Создает представление A[1,:] и представление A[0,:], затем присваивает значения A[0,:] равным тому, что находится в представлении A[1,:]. Но когда дело доходит до назначения A[1,:], представление A[0,:] теперь показывает данные после копирования, поэтому вы получаете неверный результат. В этом случае будет достаточно просто добавить .copy ко второму элементу здесь:

A[0,:], A[1,:] = A[1,:], A[0,:].copy()

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

person ShadowRanger    schedule 30.12.2017
comment
тогда почему это работает для a? Потому что это не пустые слайсы, и поэтому он копирует по умолчанию? - person Physicist; 30.12.2017
comment
@Physicist: простая индексация для одного значения создает копии (в этом случае ничего не получится, избегая копирования памяти). - person ShadowRanger; 30.12.2017