
SIE can das Basisattribut verwenden, um zu bestimmen, ob das NumPy-Array numpy.ndarray eine Ansicht oder eine Kopie ist. Darüber hinaus kann np.shares_memory() used Werden, um festzustellen, ob zwei Arrays Speicher gemeinsam nutzen.
Dieser Artikel enthält Folgendes:
- Ansicht und Kopie von numpy.ndarray
- Beispiel zum Erstellen einer Ansicht
- Beispiel für das Erstellen einer Kopie
- copy() und view()
- Festlegen, ob angezeigt oder kopiert werden soll:
base attribute
- Feststellen, ob Speicher geteilt wird:
np.shares_memory()
- Grundlegende Verwendung
- np.may_share_memory()
Die Version von NumPy im Beispielcode unten ist 1.16.4. Beachten Sie, dass sich verschiedene Versionen unterschiedlich verhalten können.
Ansicht und Kopie von numpy.ndarray
Es gibt zwei Arten von numpy.ndarray: Ansichten und Kopien.
Wenn SIE ein anderes Array-Objekt aus einem Array-Objekt erstellen, WIRD das Objekt, das Sich den Speicher mit dem ursprünglichen Objekt teilt (bezieht sich auf einen Teil oder den gesamten Speicher des ursprünglichen Objekts), als Ansicht bezeichnet.
Ausgewählt WIRD ein Objekt, das Speicher getrennt vom ursprünglichen Objekt neu zuweist, als Kopie bezeichnet.
Beispiel zum Erstellen einer Ansicht
Slices erstellen beispielsweise Ansichten.
import numpy as np
a_2d = np.arange(12).reshape(3, 4)
print(a_2d)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
a_slice = a_2d[:2, :2]
print(a_slice)
# [[0 1]
# [4 5]]
Das ursprüngliche Objekt und die Ansicht beziehen sich auf den Speicher, sodass das Ändern des Werts eines Elements in einem Objekt den Wert im anderen ändert.
a_slice[0, 0] = 100
print(a_slice)
# [[100 1]
# [ 4 5]]
print(a_2d)
# [[100 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
a_2d[0, 0] = 0
print(a_2d)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
print(a_slice)
# [[0 1]
# [4 5]]
Neben Slices geben einige Funktionen und Methoden, wie etwa reshape(), das im nächsten Abschnitt als Beispiel used WIRD, eine Ansicht zurück.
Beispiel für das Erstellen einer Kopie
Die ausgefallene Indizierung erstellte Kopien.
a_fancy_index = a_2d[[0, 1]]
print(a_fancy_index)
# [[0 1 2 3]
# [4 5 6 7]]
Da sie sich keinen Speicher teilen, ändert das Ändern des Werts eines Objekts nicht den Wert des anderen.
a_fancy_index[0, 0] = 100
print(a_fancy_index)
# [[100 1 2 3]
# [ 4 5 6 7]]
print(a_2d)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
copy() und view()
SIE can copy() verwenden, um eine Kopie eines Array-Objekts zu erstellen.
Es ist auch möglich, eine Kopie der Ansicht zu erstellen.
a_slice_copy = a_2d[:2, :2].copy()
print(a_slice_copy)
# [[0 1]
# [4 5]]
Das Ändern des Werts eines Elements eines Objekts ändert nicht den Wert des anderen.
a_slice_copy[0, 0] = 100
print(a_slice_copy)
# [[100 1]
# [ 4 5]]
print(a_2d)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
Es gibt auch eine Methode namens view().
Wenn Sie jedoch beispielsweise view() von einem Objekt aufrufen, das durch ausgefallene Indizierung erstellt wurde, wird nur die Ansicht einer Kopie zurückerstattet, nicht die Ansicht des ursprünglichen Objekts.
Festlegen, ob angezeigt oder kopiert werden soll:base attribute
Verwenden Sie das Basisattribut, um zu bestimmen, ob numpy.ndarray eine Ansicht oder eine Kopie ist (eigentlich eine Ansicht oder nicht).
Wenn numpy.ndarray eine Ansicht ist, gibt das Basisattribut das ursprüngliche numpy.ndarray zurück.
Nehmen Sie als Beispiel reshape(), das eine Ansicht so weit wie möglich zurückgibt.
a = np.arange(10)
print(a)
# [0 1 2 3 4 5 6 7 8 9]
a_0 = a[:6]
print(a_0)
# [0 1 2 3 4 5]
a_1 = a_0.reshape(2, 3)
print(a_1)
# [[0 1 2]
# [3 4 5]]
print(a_0.base)
# [0 1 2 3 4 5 6 7 8 9]
print(a_1.base)
# [0 1 2 3 4 5 6 7 8 9]
Das Basisattribut der Kopie oder des Originals numpy.ndarray (eine neu erstellte numpy.ndarray, die weder eine Kopie noch eine Ansicht ist) ist None.
a_copy = a.copy()
print(a_copy)
# [0 1 2 3 4 5 6 7 8 9]
print(a_copy.base)
# None
print(a.base)
# None
Sie können den is-Operator verwenden, um das Basisattribut mit None zu vergleichen, um festzustellen, ob es sich um eine Ansicht handelt oder nicht.
print(a_0.base is None)
# False
print(a_copy.base is None)
# True
print(a.base is None)
# True
Sie können auch sehen, dass sie sich Speicher teilen, indem Sie das Basisattribut der Ansicht mit dem ursprünglichen numpy.ndarray vergleichen oder davon, dass Sie das Basisattribut der Ansicht miteinander vergleichen.
print(a_0.base is a)
# True
print(a_0.base is a_1.base)
# True
Das folgende np.shares_memory() ist bequemer, um festzustellen, ob der Speicher gemeinsam genutzt wird.
Feststellen, ob Speicher geteilt wird:np.shares_memory()
Ob sich die beiden Arrays Speicher teilen, kann mit np.shares_memory() bestimmt werden.
Grundlegende Verwendung
Geben Sie zwei numpy.ndarrays in np.shares_memory() an. True wird zurückgegeben, wenn diese Arrays Speicher gemeinsam nutzen.
a = np.arange(6)
print(a)
# [0 1 2 3 4 5]
a_reshape = a.reshape(2, 3)
print(a_reshape)
# [[0 1 2]
# [3 4 5]]
print(np.shares_memory(a, a_reshape))
# True
Wenn SIE zwei Views angeben, sterben aus dem gemeinsamen numpy.ndarray generiert wurden, wird True ebenfalls zurückgegeben.
a_slice = a[2:5]
print(a_slice)
# [2 3 4]
print(np.shares_memory(a_reshape, a_slice))
# True
Im Falle einer Kopie wird False zurückgegeben.
a_reshape_copy = a.reshape(2, 3).copy()
print(a_reshape_copy)
# [[0 1 2]
# [3 4 5]]
print(np.shares_memory(a, a_reshape_copy))
# False
np.may_share_memory()
Es gibt auch eine ähnliche Funktion wie np.shares_memory() namens np.may_share_memory().
np.may_share_memory() ist weniger stark als np.shares_memory(), wie SIE daran sehen können, dass der Funktionsname möglicherweise enthält.
np.may_share_memory() bestimmt nur, ob sich die Speicheradressbereiche überschneiden, es berücksichtigt nicht, ob es Elemente gibt, die auf sichtbaren Speicher verweisen.
Im following Fall are sterben both Slices beispielsweise dieselbe Ansicht von numpy.ndarray und beziehen Sich auf den überlappenden Bereich, aber each Element selbst verweist auf einen anderen Speicher.
a = np.arange(10)
print(a)
# [0 1 2 3 4 5 6 7 8 9]
a_0 = a[::2]
print(a_0)
# [0 2 4 6 8]
a_1 = a[1::2]
print(a_1)
# [1 3 5 7 9]
np.shares_memory() gibt False für eine starke Beurteilung zurück, aber np.may_share_memory() gibt True zurück.
print(np.shares_memory(a_0, a_1))
# False
print(np.may_share_memory(a_0, a_1))
# True
Im folgenden Beispiel gibt np.may_share_memory() False zurück, da die Slices die erste Hälfte und die zweite Hälfte des ursprünglichen numpy.ndarray sind und sich die Bereiche nicht überschneiden.
a_2 = a[:5]
print(a_2)
# [0 1 2 3 4]
a_3 = a[5:]
print(a_3)
# [5 6 7 8 9]
print(np.shares_memory(a_2, a_3))
# False
print(np.may_share_memory(a_2, a_3))
# False
Die Verarbeitungszeit ist länger für np.shares_memory(), was eine strenge Beurteilung vornimmt. Beachten SIE, dass der folgende Code den magischen Jupyter Notebook-Befehl %%timeit used und nicht gemessen WIRD, WENN er als Python-Skript ausgeführt WIRD.
%%timeit
np.shares_memory(a_0, a_1)
# 839 ns ± 53.9 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%%timeit
np.may_share_memory(a_0, a_1)
# 275 ns ± 5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
Obwohl np.may_share_memory() fälschlicherweise True zurückgeben kann, wenn jedes Element den Speicher nicht gemeinsam nutzt, gibt es nicht fälschlicherweise False zurück, wenn der Speicher gemeinsam genutzt wird.