Aus dem Tweet hier :
import sys
x = 'ñ'
print(sys.getsizeof(x))
int(x) #throws an error
print(sys.getsizeof(x))
Wir erhalten 74, dann 77 Bytes für die beiden getsizeof
Aufrufe.
Es sieht so aus, als würden wir dem Objekt 3 Bytes aus dem fehlgeschlagenen int-Aufruf hinzufügen.
Einige weitere Beispiele von Twitter (möglicherweise müssen Sie Python neu starten, um die Größe auf 74 zurückzusetzen):
x = 'ñ'
y = 'ñ'
int(x)
print(sys.getsizeof(y))
77!
print(sys.getsizeof('ñ'))
int('ñ')
print(sys.getsizeof('ñ'))
74, dann 77.
python
string
python-3.x
unicode
python-internals
jeremycg
quelle
quelle
Antworten:
Der Code, der Zeichenfolgen in CPython 3.6 in Ints konvertiert, fordert eine UTF-8-Form der Zeichenfolge an, mit der gearbeitet werden soll :
und die Zeichenfolge erstellt die UTF-8-Darstellung beim ersten Anfordern und speichert sie im Zeichenfolgenobjekt zwischen :
if (PyUnicode_UTF8(unicode) == NULL) { assert(!PyUnicode_IS_COMPACT_ASCII(unicode)); bytes = _PyUnicode_AsUTF8String(unicode, NULL); if (bytes == NULL) return NULL; _PyUnicode_UTF8(unicode) = PyObject_MALLOC(PyBytes_GET_SIZE(bytes) + 1); if (_PyUnicode_UTF8(unicode) == NULL) { PyErr_NoMemory(); Py_DECREF(bytes); return NULL; } _PyUnicode_UTF8_LENGTH(unicode) = PyBytes_GET_SIZE(bytes); memcpy(_PyUnicode_UTF8(unicode), PyBytes_AS_STRING(bytes), _PyUnicode_UTF8_LENGTH(unicode) + 1); Py_DECREF(bytes); }
Die zusätzlichen 3 Bytes sind für die UTF-8-Darstellung.
Sie fragen sich vielleicht, warum sich die Größe nicht ändert, wenn die Zeichenfolge so etwas wie
'40'
oder ist'plain ascii text'
. Dies liegt daran , dass Python keine separate UTF-8-Darstellung erstellt, wenn sich die Zeichenfolge in einer "kompakten ASCII" -Darstellung befindet. Es gibt die ASCII-Darstellung direkt zurück , die bereits in UTF-8 gültig ist:#define PyUnicode_UTF8(op) \ (assert(_PyUnicode_CHECK(op)), \ assert(PyUnicode_IS_READY(op)), \ PyUnicode_IS_COMPACT_ASCII(op) ? \ ((char*)((PyASCIIObject*)(op) + 1)) : \ _PyUnicode_UTF8(op))
Sie fragen sich vielleicht auch, warum sich die Größe für so etwas nicht ändert
'1'
. Das ist U + FF11 FULLWIDTH DIGIT ONE, wasint
als äquivalent zu behandelt wird'1'
. Dies liegt daran, dass einer der früheren Schritte im String-to-Int-Prozess istDadurch werden alle Leerzeichen in
' '
und konvertiert alle Unicode-Dezimalstellen in die entsprechenden ASCII-Stellen. Diese Konvertierung gibt die ursprüngliche Zeichenfolge zurück, wenn am Ende nichts geändert wird. Wenn jedoch Änderungen vorgenommen werden, wird eine neue Zeichenfolge erstellt, und die neue Zeichenfolge wird mit einer UTF-8-Darstellung erstellt.In den Fällen, in denen das Aufrufen
int
einer Zeichenfolge so aussieht, als würde es eine andere betreffen, handelt es sich tatsächlich um dasselbe Zeichenfolgenobjekt. Es gibt viele Bedingungen, unter denen Python Zeichenfolgen wiederverwendet, die alle genauso fest in Weird Implementation Detail Land verankert sind wie alles, was wir bisher besprochen haben. Denn'ñ'
, geschieht die Wiederverwendung , da dies in dem Latin-1 Bereich eine Single-Zeichenkette ('\x00'
-'\xff'
) und die Implementierung gespeichert und wieder verwendet diejenigen .quelle