Überprüfen der Dokumentation zur Speicheransicht:
Mit Memoryview-Objekten kann Python-Code ohne Kopieren auf die internen Daten eines Objekts zugreifen, das das Pufferprotokoll unterstützt.
Klasse memoryview (obj)
Erstellen Sie eine Speicheransicht, die auf obj verweist. obj muss das Pufferprotokoll unterstützen. Zu den integrierten Objekten, die das Pufferprotokoll unterstützen, gehören Bytes und Bytearray.
Dann erhalten wir den Beispielcode:
>>> v = memoryview(b'abcefg')
>>> v[1]
98
>>> v[-1]
103
>>> v[1:4]
<memory at 0x7f3ddc9f4350>
>>> bytes(v[1:4])
b'bce'
Zitat vorbei, jetzt schauen wir uns das genauer an:
>>> b = b'long bytes stream'
>>> b.startswith(b'long')
True
>>> v = memoryview(b)
>>> vsub = v[5:]
>>> vsub.startswith(b'bytes')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'memoryview' object has no attribute 'startswith'
>>> bytes(vsub).startswith(b'bytes')
True
>>>
Also, was ich aus dem Obigen sammle:
Wir erstellen ein Memoryview-Objekt, um die internen Daten eines Pufferobjekts ohne Kopieren verfügbar zu machen. Um jedoch etwas Nützliches mit dem Objekt zu tun (indem wir die vom Objekt bereitgestellten Methoden aufrufen), müssen wir eine Kopie erstellen!
Normalerweise wird eine Speicheransicht (oder das alte Pufferobjekt) benötigt, wenn wir ein großes Objekt haben, und die Slices können auch groß sein. Die Notwendigkeit einer besseren Effizienz wäre vorhanden, wenn wir große Scheiben oder kleine Scheiben nur sehr oft herstellen.
Mit dem obigen Schema sehe ich nicht, wie es für beide Situationen nützlich sein kann, es sei denn, jemand kann mir erklären, was mir hier fehlt.
Edit1:
Wir haben einen großen Datenblock, den wir verarbeiten möchten, indem wir ihn von Anfang bis Ende durchlaufen, z. B. Token vom Anfang eines Zeichenfolgenpuffers extrahieren, bis der Puffer verbraucht ist. In C bedeutet dies, dass ein Zeiger durch den Code verschoben wird Puffer, und der Zeiger kann an jede Funktion übergeben werden, die den Puffertyp erwartet. Wie kann etwas Ähnliches in Python gemacht werden?
Die Leute schlagen Problemumgehungen vor, zum Beispiel verwenden viele String- und Regex-Funktionen Positionsargumente, mit denen das Vorrücken eines Zeigers emuliert werden kann. Hierbei gibt es zwei Probleme: Erstens ist es eine Problemumgehung, Sie müssen Ihren Codierungsstil ändern, um die Mängel zu beheben, und zweitens: Nicht alle Funktionen haben Positionsargumente, z. B. Regex-Funktionen und startswith
do, encode()
/ decode()
do.
Andere schlagen möglicherweise vor, die Daten in Blöcken zu laden oder den Puffer in kleinen Segmenten zu verarbeiten, die größer als das maximale Token sind. Okay, wir sind uns dieser möglichen Problemumgehungen bewusst, aber wir sollten in Python auf natürlichere Weise arbeiten, ohne zu versuchen, den Codierungsstil an die Sprache anzupassen - nicht wahr?
Edit2:
Ein Codebeispiel würde die Dinge klarer machen. Dies ist, was ich tun möchte und was ich angenommen habe, dass Memoryview es mir auf den ersten Blick ermöglichen würde. Verwenden wir pmview (richtige Speicheransicht) für die gesuchte Funktionalität:
tokens = []
xlarge_str = get_string()
xlarge_str_view = pmview(xlarge_str)
while True:
token = get_token(xlarge_str_view)
if token:
xlarge_str_view = xlarge_str_view.vslice(len(token))
# vslice: view slice: default stop paramter at end of buffer
tokens.append(token)
else:
break