Матричный вид в функции не имеет побочных эффектов - PullRequest
3 голосов
/ 23 февраля 2012

Редактировать : Я нашел, к чему сводится проблема:

Если вы запустите этот код:

A = ones((10,4))
view = A[:,1]
view.fill(7)
A

или

A = ones((10,4))
view = A[:,1:3]
view.fill(7)
A

Вы увидите, что столбцы А меняются

Если вы запустите это:

A = ones((10,4))
view = A[:,(1,2)]
view.fill(7)
A

Нет никаких побочных эффектов для A. Это поведение нарочно или ошибка?

У меня есть функция, которая вычисляет сумму, которую я должен повернуть для определенных столбцов точек x, y в матрице. Функция принимает только один вход - матричный мат:

def rotate(mat):

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

rot_mat = mat[:,(col,col+1)]

Затем я вычисляю угол поворота и применяю его обратно к виду, который я создал ранее:

rot_mat[row,0] = cos(rot)*x - sin(rot)*y
rot_mat[row,1] = sin(rot)*x + cos(rot)*y

Если я выполню это в основной части моей программы, изменения в моем представлении rot_mat будут распространяться на исходный матричный коврик. Когда я превратил его в функцию, представления перестали оказывать побочные эффекты на исходную матрицу. В чем причина этого и есть ли способ обойти это? Должен также отметить, что он не меняет коврик внутри самой функции. В конце я просто пытаюсь вернуть коврик, но никаких изменений не было.

Полный код функции:

def rotate(mat):
    # Get a reference shape
    ref_sh = 2*random.choice(range(len(filelist)))
    print 'Reference shape is '
    print (ref_sh/2)
    # Create a copy of the reference point matrix
    ref_mat = mat.take([ref_sh,ref_sh+1],axis=1)
    # Calculate rotation for each set of points
    for col in range(len(filelist)):
        col = col * 2 # Account for the two point columns
        rot_mat = mat[:,(col,col+1)]
        # Numerator = sum of wi*yi - zi*xi
        numer = inner(ref_mat[:,0],rot_mat[:,1]) - inner(ref_mat[:,1],rot_mat[:,0])
        # Denominator = sum of wi*xi + zi*yi
        denom = inner(ref_mat[:,0],rot_mat[:,0]) + inner(ref_mat[:,1],rot_mat[:,1])
        rot = arctan(numer/denom)
        # Rotate the points in rot_mat.  As it's a view of mat, the effects are
        # propagated.
        for row in range(num_points):
            x = rot_mat[row,0]
            y = rot_mat[row,1]
            rot_mat[row,0] = cos(rot)*x - sin(rot)*y
            rot_mat[row,1] = sin(rot)*x + cos(rot)*y
    return mat

1 Ответ

0 голосов
/ 24 февраля 2012

Когда вы делаете view = A[:,(1,2)], вы используете расширенное индексирование ( Руководство по Numpy: Расширенное индексирование ), что означает, что массив возвращает копию, а не представление.Это продвинуто, потому что ваш индексирующий объект - это кортеж, «содержащий по крайней мере одну последовательность» (последовательность является кортежем (1,2)).Суммарный явный объект выделения obj в вашем случае будет равен (slice(None), (1,2)), то есть A[(slice(None), (1,2))] возвращает то же самое, что и A[:,(1,2)].

Как предполагает Ларсман выше, кажется, __getitem__ и __setitem__ ведут себя иначе для расширенного индексирования, что имеет смысл, потому что присвоение значений копии не имеет смысла (копия не будет сохранена).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...