What does (numpy) __array_wrap__ do?
parla ndarray
sottoclassi e ganci come __array_wrap__
. np.array
prende il parametro copy
, forzando il risultato a essere una copia, anche se non è richiesto da altre considerazioni. ravel
restituisce una vista, flatten
una copia. Quindi è probabilmente possibile, e forse non troppo difficile, costruire una sottoclasse ndarray
che impone una copia. Potrebbe comportare la modifica di un hook come __array_wrap__
.
Oppure modificare il metodo .__getitem__
. L'indicizzazione come in slice_of_arr = arr[0:6]
implica una chiamata a __getitem__
. Per ndarray
questo viene compilato, ma per un array mascherato, è il codice python che si potrebbe usare come esempio:
/usr/lib/python3/dist-packages/numpy/ma/core.py
Può essere qualcosa di semplice come
def __getitem__(self, indx):
"""x.__getitem__(y) <==> x[y]
"""
# _data = ndarray.view(self, ndarray) # change to:
_data = ndarray.copy(self, ndarray)
dout = ndarray.__getitem__(_data, indx)
return dout
Ma ho il sospetto che da nel momento in cui sviluppi e collaudi completamente una sottoclasse di questo tipo, potresti innamorarti dell'approccio no-copy predefinito. Mentre questo business view-v-copy morde molti nuovi arrivati (specialmente se provengono da MATLAB), non ho visto lamentele da parte di utenti esperti. Guarda altre domande SO assordanti; non vedrai molte chiamate copy()
.
Anche gli utenti regolari di Python si chiedono se un riferimento o una sezione è una copia o meno e se qualcosa è mutabile o meno.
ad esempio con le liste:
In [754]: ll=[1,2,[3,4,5],6]
In [755]: llslice=ll[1:-1]
In [756]: llslice[1][1:2]=[10,11,12]
In [757]: ll
Out[757]: [1, 2, [3, 10, 11, 12, 5], 6]
modificando una voce di un elemento all'interno di una fetta modifica quello stesso elemento nella lista originale. A differenza di numpy
, una sezione elenco è una copia. Ma è una copia superficiale. Devi fare uno sforzo extra per fare una copia profonda (import copy
).
/usr/lib/python3/dist-packages/numpy/lib/index_tricks.py
contiene alcune funzioni di indicizzazione per rendere più convenienti determinate operazioni di indicizzazione. Diverse sono in realtà classi o istanze di classe con i metodi personalizzati __getitem__
. Possono anche fungere da modelli per personalizzare il taglio e l'indicizzazione.
È progettato in questo modo per le prestazioni e l'implementazione ad es. il copy-on-write sarebbe probabilmente ancora più confuso. Perché questo design è un problema per te? – Krumelur
@Krumelur Perché nella maggior parte degli scenari di programmazione non scientifica, è così che funziona. E penso che non ci sia equivalenza in 'matlab'.Devo "ricordare" questo comportamento, e in realtà non mi piace la "ripetizione" nella programmazione. – cqcn1991
OK, abbastanza giusto. Immagino che sarebbe un compromesso tra la pulizia del codice che affetta le matrici e il codice, ad es. 'DoSomething (arr [6000])'. Penso che Matlab faccia CoW per risolvere questo. – Krumelur