PEP 467 – Kleinere API-Verbesserungen für binäre Sequenzen
- Autor:
- Alyssa Coghlan <ncoghlan at gmail.com>, Ethan Furman <ethan at stoneleaf.us>
- Discussions-To:
- Discourse thread
- Status:
- Entwurf
- Typ:
- Standards Track
- Erstellt:
- 30-Mär-2014
- Python-Version:
- 3.15
- Post-History:
- 30-Mär-2014, 15-Aug-2014, 16-Aug-2014, 07-Jun-2016, 01-Sep-2016, 13-Apr-2021, 03-Nov-2021, 27-Dez-2023
Inhaltsverzeichnis
Zusammenfassung
Dieser PEP schlägt kleine Anpassungen der APIs der bytes und bytearray Typen vor, um die Arbeit vollständig im binären Bereich zu erleichtern.
- Hinzufügung des alternativen Konstruktors
fromsize - Hinzufügung des alternativen Konstruktors
fromint - Hinzufügung der Byte-Abruf-Methode
getbyte - Hinzufügung des alternativen Iterators
iterbytes
Die letzten beiden (getbyte und iterbytes) werden auch zu memoryview hinzugefügt.
Begründung
Während der anfänglichen Entwicklung der Python 3-Sprachspezifikation begann der Kern-bytes-Typ für beliebige Binärdaten als der mutable Typ, der jetzt als bytearray bezeichnet wird. Andere Aspekte der Arbeit im binären Bereich haben sich im Laufe der Python 3-Serie ebenfalls weiterentwickelt, zum Beispiel mit PEP 461.
Motivation
Mit Python 3 und der Trennung zwischen str und bytes wurde ein kleiner, aber wichtiger Programmierbereich etwas schwieriger und viel schmerzhafter – Wire-Format-Protokolle.
Dieser Programmierbereich zeichnet sich durch eine Mischung aus Binärdaten und ASCII-kompatiblen Textsegmenten (auch ASCII-kodierter Text genannt) aus. Die Hinzufügung der neuen Konstruktoren, Methoden und Iteratoren wird sowohl beim Schreiben neuer Wire-Format-Codes als auch bei der Aktualisierung bestehender Codes helfen.
Häufige Anwendungsfälle sind dbf- und pdf-Dateiformate, email-Formate und FTP- und HTTP-Kommunikation, unter vielen anderen.
Vorschläge
Hinzufügung von expliziten „Konstruktoren für Anzahl und Byte-initialisierte Sequenzen“
Um das nicht mehr empfohlene Verhalten, Null-gefüllte bytes-ähnliche Objekte aus den grundlegenden Konstruktoren zu erstellen (d.h. bytes(1) -> b'\x00'), schlägt dieser PEP die Hinzufügung eines expliziten alternativen Konstruktors fromsize als Klassenmethode auf bytes und bytearray vor, dessen erstes Argument die Anzahl und dessen zweites Argument das zu verwendende Füllbyte ist (standardmäßig \x00).
>>> bytes.fromsize(3)
b'\x00\x00\x00'
>>> bytearray.fromsize(3)
bytearray(b'\x00\x00\x00')
>>> bytes.fromsize(5, b'\x0a')
b'\x0a\x0a\x0a\x0a\x0a'
>>> bytearray.fromsize(5, fill=b'\x0a')
bytearray(b'\x0a\x0a\x0a\x0a\x0a')
fromsize verhält sich genauso wie die aktuellen Konstruktoren, wenn sie mit einer einzelnen Ganzzahl aufgerufen werden, und ermöglicht bei Bedarf nicht-null Füllwerte.
Hinzufügung von expliziten „Ein-Byte“-Konstruktoren
Als binäre Gegenstücke zur Textfunktion chr schlägt dieser PEP die Hinzufügung eines expliziten alternativen Konstruktors fromint als Klassenmethode auf bytes und bytearray vor.
>>> bytes.fromint(65)
b'A'
>>> bytearray.fromint(65)
bytearray(b'A')
Diese Methoden akzeptieren nur Ganzzahlen im Bereich von 0 bis 255 (einschließlich).
>>> bytes.fromint(512)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: integer must be in range(0, 256)
>>> bytes.fromint(1.0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'float' object cannot be interpreted as an integer
Die Dokumentation der ord-Builtin wird aktualisiert, um explizit darauf hinzuweisen, dass bytes.fromint die primäre inverse Operation für Binärdaten ist, während chr die inverse Operation für Textdaten ist und dass bytearray.fromint ebenfalls existiert.
Verhaltenstechnisch ist bytes.fromint(x) äquivalent zum aktuellen bytes([x]) (und ähnlich für bytearray). Die neue Schreibweise wird voraussichtlich leichter zu entdecken und besser lesbar sein (insbesondere in Verbindung mit Indexierungsoperationen auf binären Sequenztypen).
Als separate Methode wird die neue Schreibweise auch besser mit höheren Funktionen wie map funktionieren.
Diese neuen Methoden bieten absichtlich NICHT das gleiche Maß an allgemeiner Ganzzahlunterstützung wie die bestehende Konvertierungsmethode int.to_bytes, die beliebig große Ganzzahlen in beliebig lange Bytes-Objekte konvertiert. Die Beschränkung auf die Annahme positiver Ganzzahlen, die in ein einzelnes Byte passen, bedeutet, dass keine Byte-Reihenfolge-Informationen benötigt werden und keine negativen Zahlen behandelt werden müssen. Die Dokumentation der neuen Methoden wird Leser auf int.to_bytes für Anwendungsfälle verweisen, bei denen die Handhabung von beliebigen Ganzzahlen erforderlich ist.
Hinzufügung der Methode „getbyte“ zum Abrufen eines einzelnen Bytes
Dieser PEP schlägt vor, dass bytes, bytearray und memoryview die Methode getbyte erhalten, die immer bytes zurückgibt.
>>> b'abc'.getbyte(0)
b'a'
Wenn ein nicht vorhandener Index angefordert wird, wird ein IndexError ausgelöst.
>>> b'abc'.getbyte(9)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: index out of range
Hinzufügung von optimierten Iterator-Methoden, die bytes-Objekte erzeugen
Dieser PEP schlägt vor, dass bytes, bytearray und memoryview eine optimierte iterbytes-Methode erhalten, die Längen-1 bytes-Objekte anstelle von Ganzzahlen erzeugt.
for x in data.iterbytes():
# x is a length 1 ``bytes`` object, rather than an integer
Zum Beispiel:
>>> tuple(b"ABC".iterbytes())
(b'A', b'B', b'C')
Design-Diskussion
Warum nicht auf Sequenzwiederholung zurückgreifen, um Null-initialisierte Sequenzen zu erstellen?
Null-initialisierte Sequenzen können über Sequenzwiederholung erstellt werden.
>>> b'\x00' * 3
b'\x00\x00\x00'
>>> bytearray(b'\x00') * 3
bytearray(b'\x00\x00\x00')
Dies war jedoch auch der Fall, als der bytearray-Typ ursprünglich entworfen wurde, und es wurde die Entscheidung getroffen, ihn im Typkonstruktor explizit zu unterstützen. Der unveränderliche bytes-Typ erbte dann dieses Feature, als er in PEP 3137 eingeführt wurde.
Dieser PEP revisitiert diese ursprüngliche Designentscheidung nicht, sondern ändert nur die Schreibweise, da Benutzer das aktuelle Verhalten der binären Sequenzkonstruktoren manchmal überraschend finden. Insbesondere gibt es ein vernünftiges Argument dafür, dass bytes(x) (wobei x eine Ganzzahl ist) sich wie der bytes.fromint(x)-Vorschlag in diesem PEP verhalten sollte. Beide Verhaltensweisen als separate Klassenmethoden bereitzustellen, vermeidet diese Mehrdeutigkeit.
Aktuelle Workarounds
Nach fast einem Jahrzehnt scheint es keinen Konsens über die besten Workarounds für die Byte-Iteration zu geben, wie die Diskussion „Get single-byte bytes objects from bytes objects“ zeigt.
Weglassen der ursprünglich vorgeschlagenen Builtin-Funktion
Als er dem Steering Council vorgelegt wurde, schlug dieser PEP die Einführung einer bchr-Builtin (mit gleichem Verhalten wie bytes.fromint) vor, wodurch das Trio ord/chr/unichr aus Python 2 unter einem anderen Namensschema (ord/bchr/chr) wiederbelebt wurde.
Das SC gab an, dass es diese Funktionalität nicht oft genug für notwendig hielt, um zwei Wege für dasselbe zu rechtfertigen, insbesondere wenn einer dieser Wege eine neue Builtin-Funktion war. Dieser Teil des Vorschlags wurde daher als redundant mit dem alternativen Konstruktor bytes.fromint fallen gelassen.
Entwickler, die diese Methode häufig verwenden, haben stattdessen die Möglichkeit, ihre eigenen bchr = bytes.fromint Aliase zu definieren.
Referenzen
- Erste Diskussions-Thread vom März 2014 auf python-ideas
- Guido's erstes Feedback in diesem Thread
- Issue, die die Verschiebung von Null-initialisierten Sequenzen in eine dedizierte API vorschlägt
- Issue, die die Verwendung von calloc() für Null-initialisierte binäre Sequenzen vorschlägt
- Diskussions-Thread vom August 2014 auf python-dev
- Diskussions-Thread vom Juni 2016 auf python-dev
- Ein-Byte-Bytes-Objekte aus Bytes-Objekten abrufen
Urheberrecht
Dieses Dokument wurde gemeinfrei erklärt.
Quelle: https://github.com/python/peps/blob/main/peps/pep-0467.rst
Zuletzt geändert: 2025-05-06 21:00:16 GMT