Was bedeutet "drei Punkte" in Python beim Indizieren einer Zahl?

Antworten:

70

Während des vorgeschlagenen Duplikats Was macht das Python Ellipsis-Objekt? beantwortet die Frage in einem allgemeinen pythonKontext, ihre Verwendung in einer nditerSchleife erfordert, denke ich, zusätzliche Informationen.

https://docs.scipy.org/doc/numpy/reference/arrays.nditer.html#modifying-array-values

Durch die regelmäßige Zuweisung in Python wird einfach eine Referenz im lokalen oder globalen Variablenwörterbuch geändert, anstatt eine vorhandene Variable zu ändern. Dies bedeutet, dass durch einfaches Zuweisen zu x der Wert nicht in das Element des Arrays eingefügt wird, sondern dass x von einer Array-Elementreferenz zu einer Referenz auf den von Ihnen zugewiesenen Wert wechselt. Um das Element des Arrays tatsächlich zu ändern, sollte x mit den Auslassungspunkten indiziert werden.

Dieser Abschnitt enthält Ihr Codebeispiel.

In meinen Worten x[...] = ...ändert sich das xan Ort und Stelle; x = ...hätte den Link zur nditerVariablen unterbrochen und nicht geändert. Es ist wie x[:] = ..., funktioniert aber mit Arrays jeder Dimension (einschließlich 0d). In diesem Zusammenhang xist es nicht nur eine Zahl, sondern ein Array.

Vielleicht ist das, was dieser nditerIteration am nächsten kommt , ohne nditer:

In [667]: for i, x in np.ndenumerate(a):
     ...:     print(i, x)
     ...:     a[i] = 2 * x
     ...:     
(0, 0) 0
(0, 1) 1
...
(1, 2) 5
In [668]: a
Out[668]: 
array([[ 0,  2,  4],
       [ 6,  8, 10]])

Beachten Sie, dass ich a[i]direkt indizieren und ändern musste . Ich hätte nicht benutzen können , x = 2*x. In dieser Iteration xist ein Skalar und somit nicht veränderbar

In [669]: for i,x in np.ndenumerate(a):
     ...:     x[...] = 2 * x
  ...
TypeError: 'numpy.int32' object does not support item assignment

In diesem nditerFall xhandelt es sich jedoch um ein 0d-Array, das veränderbar ist.

In [671]: for x in np.nditer(a, op_flags=['readwrite']):
     ...:     print(x, type(x), x.shape)
     ...:     x[...] = 2 * x
     ...:     
0 <class 'numpy.ndarray'> ()
4 <class 'numpy.ndarray'> ()
...

Und weil es 0d ist, x[:]kann nicht anstelle von verwendet werdenx[...]

----> 3     x[:] = 2 * x
IndexError: too many indices for array

Eine einfachere Array-Iteration könnte auch Einblicke geben:

In [675]: for x in a:
     ...:     print(x, x.shape)
     ...:     x[:] = 2 * x
     ...:     
[ 0  8 16] (3,)
[24 32 40] (3,)

Dies iteriert in den Zeilen (1. Abm.) von a. xist dann ein 1d-Array und kann mit entweder x[:]=...oder geändert werden x[...]=....

Und wenn ich das external_loopFlag aus dem nächsten Abschnitt hinzufüge , xist es jetzt ein 1d-Array und x[:] =würde funktionieren. Funktioniert aber x[...] =immer noch und ist allgemeiner. x[...]wird alle anderen nditerBeispiele verwendet.

In [677]: for x in np.nditer(a, op_flags=['readwrite'], flags=['external_loop']):
     ...:     print(x, type(x), x.shape)
     ...:     x[...] = 2 * x
[ 0 16 32 48 64 80] <class 'numpy.ndarray'> (6,)

Vergleichen Sie diese einfache Zeileniteration (auf einem 2d-Array):

In [675]: for x in a:
     ...:     print(x, x.shape)
     ...:     x[:] = 2 * x
     ...:     
[ 0  8 16] (3,)
[24 32 40] (3,)

Dies iteriert in den Zeilen (1. Abm.) von a. xist dann ein 1d-Array und kann mit entweder x[:] = ...oder geändert werden x[...] = ....

Lesen und experimentieren Sie mit dieser nditerSeite bis zum Ende. An sich nditerist das nicht so nützlich in python. Die Iteration wird nicht beschleunigt - erst, wenn Sie Ihren Code auf portieren cython. np.ndindexist eine der wenigen nicht kompilierten numpyFunktionen, die verwendet werden nditer.

hpaulj
quelle
Beachten Sie, dass Dinge wie x [1,:, ...] ebenfalls eine zulässige Syntax sind. Links zum späteren Nachschlagen.
Borgr