Modifica dell'array NumPy in una funzione [duplicato]

Sep 29 2020

Il codice seguente

def change(in_array):

    in_array += 1             # line a

    in_array = in_array + 1   # line b


x = np.array([1, 2, 3])
change(x)
print(x)

stampe [2 3 4]. Perché è così (perché le due righe aeb sono diverse)? Potresti suggerire altri modi per modificare l'array NumPy come si fa nella riga a? Un modo sarebbe in_array[:] = in_array + 1; i valori della matrice passata verrebbero sempre modificati in caso di in_array[:] = ...?

Risposte

Arty Sep 28 2020 at 22:35

Vediamo il prossimo codice:

Provalo online!

import numpy as np

def change(in_array, variant = 0):
    if variant == 0:
        in_array += 1             # line a
    elif variant == 1:
        in_array = in_array + 1   # line b
    elif variant == 2:
        in_array[:] = in_array + 1
    elif variant == 3:
        np.put(in_array, np.arange(in_array.size), in_array + 1)
    elif variant == 4:
        np.copyto(in_array, in_array + 1)
    elif variant == 5:
        np.place(in_array, np.ones_like(in_array), in_array + 1)
    else:
        assert False, variant
    print('after, inside', in_array)

orig = np.array([1, 2, 3])
for variant in [0, 1, 2, 3, 4, 5]:
    print('variant', variant)
    x = np.copy(orig)
    print('before', x)
    change(x, variant)
    print('after, outside', x, ('changed', 'not changed')[bool(np.all(x == orig))])

Emette:

variant 0
before [1 2 3]
after, inside [2 3 4]
after, outside [2 3 4] changed
variant 1
before [1 2 3]
after, inside [2 3 4]
after, outside [1 2 3] not changed
variant 2
before [1 2 3]
after, inside [2 3 4]
after, outside [2 3 4] changed
variant 3
before [1 2 3]
after, inside [2 3 4]
after, outside [2 3 4] changed
variant 4
before [1 2 3]
after, inside [2 3 4]
after, outside [2 3 4] changed
variant 5
before [1 2 3]
after, inside [2 3 4]
after, outside [2 3 4] changed

Potresti vedere che la variante 0 dà la risposta corretta all'interno e all'esterno. Mentre la variante 1 dà la correzione solo all'interno.

Questo perché la variante 0 modifica l'array effettivamente dato fornito nella funzione. Mentre la variante 1 crea una copia modificata all'interno della funzione che rimane solo all'interno della funzione, l'argomento effettivamente passato non viene modificato.

Quindi la variante 0 modifica l'argomento passato, mentre la variante 1 modifica una copia dell'argomento passato.

Nel codice Python a = a + 1all'interno di una funzione crea effettivamente una copia della variabile alocal in function. E questa variabile locale rimane solo fino alla fine della funzione e viene eliminata alla fine della funzione in esecuzione.

La variante 2, a[:]crea la vista dell'array originale, è come un riferimento a un sottoinsieme di elementi dell'array originale, :è solo la vista dell'intero array, l'assegnazione a questa vista modifica l'array originale. La vista modificabile viene creata anche da sezioni simili a[1:3]e indicizzazioni simili a[2]o a[[1,2]].

La scrittura a[:] = some_operation(a)è probabilmente il modo più intuitivo e veloce per riassegnare una acopia modificata / trasformata di a.

Le varianti 3, 4, 5 sono altri modi fantasiosi per assegnare l'espressione del lato destro all'array a.