Mal sehen, kann ich erklären, was genau wie ll
auf
In [32]: ll=['one','two','three']
In [33]: a1=np.array(ll,dtype=object)
In [34]: a1
Out[34]: array(['one', 'two', 'three'], dtype=object)
In [35]: a1[1]='eleven'
In [36]: a1
Out[36]: array(['one', 'eleven', 'three'], dtype=object)
a1
los ist besteht aus Zeigern - Zeiger auf Strings, die sich anderswo im Speicher befinden. Ich kann jeden dieser Zeiger ändern, genauso wie ich es in einer Liste tun könnte. In den meisten Fällen verhält sich a1
genau wie eine Liste - außer dass es möglich ist, umzugestalten, und einige andere grundlegende array
Dinge zu tun.
In [37]: a1.reshape(3,1)
Out[37]:
array([['one'],
['eleven'],
['three']], dtype=object)
Aber wenn ich eine string
Array
In [38]: a2=np.array(ll)
In [39]: a2
Out[39]:
array(['one', 'two', 'three'],
dtype='<U5')
In [42]: a1.itemsize
Out[42]: 4
In [43]: a2.itemsize
Out[43]: 20
die Werte in den Datenpuffer des Array gespeichert sind. Hier wurde ein Array mit 5 Unicode-Zeichen pro Element (Python3) erstellt (jeweils 5 * 4 Bytes).
Nun, wenn ich ein Element der a2
ersetzen kann ich Abschneiden
In [44]: a2[1]='eleven'
In [45]: a2
Out[45]:
array(['one', 'eleve', 'three'],
dtype='<U5')
weil nur 5 der Zeichen des neuen Wertes fit in den zugewiesenen Raum bekommen.
Es gibt also einen Kompromiss aus - schnellere Zugriffsgeschwindigkeit, weil die Bytes in einem festen Array bekannter Größe gespeichert sind, aber Sie können größere Dinge nicht speichern.
könnten Sie mehr Platz pro Element zuordnen:
In [46]: a3=np.array(ll,dtype='|U10')
In [47]: a3
Out[47]:
array(['one', 'two', 'three'],
dtype='<U10')
In [48]: a3[1]='eleven'
In [49]: a3
Out[49]:
array(['one', 'eleven', 'three'],
dtype='<U10')
genfromtxt
ist ein übliches Werkzeug für Arrays mit String dtypes zu schaffen. Das wartet, bis es die gesamte Datei gelesen hat, bevor die Zeichenfolgenlänge festgelegt wird (zumindest wenn dtype=None
verwendet wird). Und die String-Felder sind oft Teil eines Arrays mit mehreren Feldern. Die Zeichenfolgenfelder sind normalerweise Beschriftungen oder IDs, die Sie normalerweise nicht ändern.
Ich kann mir vorstellen, eine Funktion schreiben, die String-Länge gegen den dtype überprüfen würde und einen Fehler auslösen, wenn die Kürzung passieren würde. Aber das wird die Aktion verlangsamen.
def foo(A, i, astr):
if A.itemsize/4<len(astr):
raise ValueError('too long str')
A[i] = astr
In [69]: foo(a2,1,'four')
In [70]: a2
Out[70]:
array(['one', 'four', 'three'],
dtype='<U5')
In [72]: foo(a2,1,'eleven')
...
ValueError: too long str
aber ist es die zusätzliche Arbeit wert?
*“... eine Ausnahme im Fall der Kürzung erhöhen ? "* Es wäre schön, wenn das Setzen eines Flags dieses Verhalten aktiviert, vielleicht etwas ähnlich wie' numpy.seterr() 'die Handhabung von Gleitkommafehlern steuert. Ich habe noch nie eine solche Flagge gesehen, aber als Verbesserungsanfrage für numpy würde ich es +1 geben. –
@WarrenWeckesser. Ich stimme zu, es könnte auch eine Warnung oder etwas Ähnliches sein. –