Поведение, подобное указателю, в операторе присваивания при работе с массивами numpy? - PullRequest
1 голос
/ 14 июля 2020

Я наткнулся на странное поведение оператора присваивания + =, которое меня полностью утомляет. См. Этот фрагмент кода:


import numpy as np

def myalg(data, alpha, beta):

    adash=np.zeros(len(data))
    a=np.zeros_like(adash)
    a_=np.zeros_like(a)
    gain=1
    count=0

    while count<3:
        adash=adash+alpha*np.gradient(data)
        a_old=a
        print( a_old)
        #a+=alpha* (np.gradient(adash)+ alpha* data)
        a=a+alpha* (np.gradient(adash)+  alpha* data)
        print( a_old)
        a/=1+alpha*beta
        #a=a/(1+alpha*beta)
        print( a_old)
        a_=2*a-a_old
        
        gain=la.norm(a-a_old)
        count+=1 
        print(a)
        print(a_)
        print(adash)
        print(gain)

data=np.arange(6)
myalg(data, alpha=0.4, beta=0.25)

Я ожидал, что ничего не изменится при замене одного из «комментариев» на указанную выше альтернативную строку. И хотя массив a действительно один и тот же в каждом случае, код действительно меняется a_old: при выборе a=a+..., a_old остается неизменным, независимо от того, какой из a/= или a=a/... выбран. ниже. Однако при выборе оператора присваивания a+=, a_old ведет себя как «указатель» на a. Таким образом, print(a_old) возвращает значение a каждый раз, когда он вызывается, пока a не будет явно присвоено новое значение (например, a= a/... вместо оператора присваивания, такого как +=, -=, *=, /=).

Итак почему это происходит с массивами?

РЕДАКТИРОВАТЬ: Я вижу, КАК это происходит, но я не понимаю, ПОЧЕМУ это происходит. Почему этого не происходит, например, с целыми числами или числами с плавающей запятой?

1 Ответ

0 голосов
/ 14 июля 2020

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

#This points to `a`
a_old=a
print(a_old)

    #This changes `a` inplace so `a_old` will change too
    a+=alpha* (np.gradient(adash)+ alpha* data)
    
    #This creates a NEW `a`, therefore `a_old` will not change
    a=a+alpha* (np.gradient(adash)+  alpha* data)

print(a_old)

    #if you have used `a+=..` this changes `a` inplace again and so `a_old`
    #if you have used `a=a+..` this changes the NEW `a` and NOT the `a_old`
    a/=1+alpha*beta

    #this creates yet another NEWER `a` 
    #and hence `a_old` does not change beyond the LAST print
    a=a/(1+alpha*beta)

print(a_old)
...