2015-07-23 15 views
6
arr = np.arange(0,11) 
slice_of_arr = arr[0:6] 
slice_of_arr[:]=99 

# slice_of_arr returns 
array([99, 99, 99, 99, 99, 99]) 
# arr returns 
array([99, 99, 99, 99, 99, 99, 6, 7, 8, 9, 10]) 

Jako przykład pokazany powyżej, nie można bezpośrednio zmienić wartości slice_of_arr, ponieważ jest to widok arr, a nie nowa zmienna.NumPy: Dlaczego trzeba jawnie skopiować wartość?

Moje pytania są następujące:

  1. Dlaczego NumPy projekt w taki sposób? Czy nie byłoby nudne za każdym razem, gdy potrzebujesz .copy, a następnie przypisujesz wartość?
  2. Czy jest coś, co mogę zrobić, aby pozbyć się .copy? Jak mogę zmienić to domyślne zachowanie NumPy?
+9

Zaprojektowano go tak, by działał wydajnie i implementował np. kopiowanie przy pisaniu byłoby prawdopodobnie jeszcze bardziej zagmatwane. Dlaczego ten wzór jest dla ciebie problemem? – Krumelur

+0

@Krumelur Ponieważ w większości nienaukowych scenariuszy programowania, tak to działa. I myślę, że nie ma również równoważności w 'matlab'.Muszę "zapamiętać" to zachowanie i naprawdę nie lubię "repetacji" w programowaniu. – cqcn1991

+0

OK, wystarczy. Sądzę, że byłby to kompromis pomiędzy czystością kodu, który kroi tablice i kod, np. 'doSomething (arr [: 6000])'. Myślę, że Matlab robi COŚ, aby to rozwiązać. – Krumelur

Odpowiedz

0

What does (numpy) __array_wrap__ do?

mówi o ndarray podklasy i haki jak __array_wrap__. np.array Parametr jest wymuszany, zmuszając wynik do kopii, nawet jeśli nie jest to wymagane przez inne czynniki. ravel zwraca widok, flatten kopię. Jest więc możliwe, i być może niezbyt trudne, skonstruowanie podklasy ndarray, która wymusza kopiowanie. Może to wymagać zmodyfikowania haka, takiego jak __array_wrap__.

A może modyfikując metodę .__getitem__. Indeksowanie jak w slice_of_arr = arr[0:6] obejmuje połączenie z numerem __getitem__. Dla ndarray ten jest kompilowany, ale zamaskowany tablicy, to kod Pythona, który można użyć jako przykładu:

/usr/lib/python3/dist-packages/numpy/ma/core.py 

może to być coś tak prostego jak

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 

Ale podejrzewam, że przez czas, w którym rozwijasz i w pełni testujesz taką podklasę, możesz zakochać się w domyślnym podejściu bez kopiowania. Podczas gdy ten widok-v-kopia ugryźć wielu nowych klientów (zwłaszcza jeśli pochodzą z MATLAB), nie widziałem skarg od doświadczonych użytkowników. Spójrz na inne numpy pytania SO; nie zobaczysz wiele połączeń copy().

Używa się nawet zwykłych użytkowników Pythona, zadając sobie pytanie, czy odniesienie lub plaster jest kopią czy nie i czy coś jest zmienne czy nie.

na przykład z list:

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] 

modyfikacji elementu element wewnątrz plasterka modyfikuje ten sam element w oryginalnej listy. W przeciwieństwie do numpy, wycinek listy jest kopią. Ale to płytka kopia. Musisz wykonać dodatkowy wysiłek, aby wykonać głęboką kopię (import copy).

/usr/lib/python3/dist-packages/numpy/lib/index_tricks.py zawiera funkcje indeksowania, które mają na celu uczynienie niektórych operacji indeksowania wygodniejszymi. Kilka to faktycznie klasy lub instancje klas z niestandardowymi metodami __getitem__. Mogą również służyć jako modele dostosowywania sposobu krojenia i indeksowania.

Powiązane problemy