Was ist der Unterschied zwischen einer Zeichenfolge und einer Byte-Zeichenfolge?

209

Ich arbeite mit einer Bibliothek, die eine Byte-Zeichenfolge zurückgibt, und ich muss diese in eine Zeichenfolge konvertieren.

Obwohl ich nicht sicher bin, was der Unterschied ist - wenn überhaupt.

Sheldon
quelle

Antworten:

260

Angenommen, Python 3 (in Python 2 ist dieser Unterschied etwas weniger genau definiert) - eine Zeichenfolge ist eine Folge von Zeichen, dh Unicode-Codepunkten ; Dies ist ein abstraktes Konzept und kann nicht direkt auf der Festplatte gespeichert werden. Ein Byte - String ist eine Folge von, wenig überraschend, Byte - Dinge , die können auf der Festplatte gespeichert werden. Die Zuordnung zwischen ihnen ist eine Codierung - es gibt ziemlich viele davon (und unendlich viele sind möglich) - und Sie müssen wissen, welche im jeweiligen Fall gilt, um die Konvertierung durchzuführen, da eine andere Codierung dieselben Bytes zuordnen kann zu einer anderen Zeichenfolge:

>>> b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82'.decode('utf-16')
'蓏콯캁澽苏'
>>> b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82'.decode('utf-8')
'τoρνoς'

Sobald Sie wissen, welche Sie verwenden sollen, können Sie die .decode()Methode der Byte-Zeichenfolge verwenden, um wie oben die richtige Zeichenfolge daraus zu erhalten. Der Vollständigkeit .encode()halber geht die Methode einer Zeichenkette in die entgegengesetzte Richtung:

>>> 'τoρνoς'.encode('utf-8')
b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82'
lvc
quelle
7
Zur Verdeutlichung für Python 2-Benutzer: Der strTyp ist der gleiche wie der bytesTyp. Diese Antwort vergleicht den unicodeTyp (der in Python 3 nicht vorhanden ist) mit dem strTyp.
Craymichael
2
@ KshitijSaraogi das stimmt auch nicht ganz; Dieser ganze Satz wurde in bearbeitet und ist ein bisschen unglücklich. Die speicherinterne Darstellung von Python 3- strObjekten ist von Python-Seite nicht zugänglich oder relevant. Die Datenstruktur ist nur eine Folge von Codepunkten. Unter PEP 393 ist die genaue interne Codierung eine von Latin-1, UCS2 oder UCS4, und eine utf-8-Darstellung kann nach der ersten Anforderung zwischengespeichert werden, aber selbst C-Code wird davon abgehalten, sich auf diese internen Details zu verlassen.
lvc
1
Wenn sie nicht direkt auf der Festplatte gespeichert werden können, wie werden sie dann im Speicher gespeichert?
z33k
1
@orety sie müssen aus genau diesem Grund irgendwie intern codiert werden , aber dies ist für Sie kein Expos3s aus Python-Code, ähnlich wie Sie sich nicht darum kümmern müssen, wie Gleitkommazahlen gespeichert werden.
lvc
1
@ChrisStryczynski siehe die obigen Kommentare - sicher, dass sie irgendwie im Speicher gespeichert sind , aber dieses Formular wird explizit weg abstrahiert. In der Tat kann es sich heutzutage während der Lebensdauer eines Programms ändern und zwischen verschiedenen Zeichenfolgen unterschiedlich sein oder sogar mehr als eine (einige Codierungen werden zwischengespeichert), abhängig von den darin enthaltenen Zeichen - aber das einzige Mal, über das Sie sich Sorgen machen müssen Dies ist der Fall, wenn Sie die Implementierung des Zeichenfolgentyps selbst hacken.
lvc
390

Das einzige, was ein Computer speichern kann, sind Bytes.

Um etwas auf einem Computer zu speichern, müssen Sie es zuerst codieren , dh in Bytes konvertieren. Beispielsweise:

  • Wenn Sie Musik speichern möchten, müssen Sie zunächst kodieren sie mit MP3, WAVusw.
  • Wenn Sie ein Bild speichern möchten, müssen Sie zunächst kodieren sie mit PNG, JPEGusw.
  • Wenn Sie Text speichern möchten, müssen Sie zunächst kodieren sie mit ASCII, UTF-8usw.

MP3, WAV, PNG, JPEG, ASCIIUnd UTF-8sind Beispiele für Codierungen . Eine Codierung ist ein Format zur Darstellung von Audio, Bildern, Text usw. in Bytes.

In Python ist eine Byte-Zeichenfolge genau das: eine Folge von Bytes. Es ist nicht für Menschen lesbar. Unter der Haube muss alles in eine Byte-Zeichenfolge konvertiert werden, bevor es in einem Computer gespeichert werden kann.

Andererseits ist eine Zeichenfolge, die oft nur als "Zeichenfolge" bezeichnet wird, eine Folge von Zeichen. Es ist für Menschen lesbar. Eine Zeichenfolge kann nicht direkt auf einem Computer gespeichert werden, sondern muss zuerst codiert (in eine Bytezeichenfolge konvertiert) werden. Es gibt mehrere Codierungen, durch die eine Zeichenfolge in eine Bytezeichenfolge wie ASCIIund konvertiert werden kann UTF-8.

'I am a string'.encode('ASCII')

Der obige Python-Code codiert die Zeichenfolge 'I am a string'mithilfe der Codierung ASCII. Das Ergebnis des obigen Codes ist eine Bytezeichenfolge. Wenn Sie es drucken, wird es von Python als dargestelltb'I am a string' . Denken Sie jedoch daran, dass Byte-Strings nicht für Menschen lesbar sind. Python dekodiert sie nur, ASCIIwenn Sie sie drucken. In Python wird eine Bytezeichenfolge durch a dargestellt b, gefolgt von der ASCIIDarstellung der Bytezeichenfolge .

Eine Byte-Zeichenfolge kann sein wieder in eine Zeichenfolge dekodiert werden , wenn Sie die Codierung kennen, mit der sie codiert wurde.

b'I am a string'.decode('ASCII')

Der obige Code gibt die ursprüngliche Zeichenfolge zurück 'I am a string'.

Codierung und Decodierung sind inverse Operationen. Alles muss codiert sein, bevor es auf die Festplatte geschrieben werden kann, und es muss decodiert werden, bevor es von einem Menschen gelesen werden kann.

Zenadix
quelle
59
Zenadix verdient hier ein Lob. Nach einigen Jahren in dieser Umgebung ist dies die erste Erklärung, die bei mir geklickt hat. Ich kann es auf meinen anderen Arm tätowieren (ein Arm hat bereits "Das absolute Minimum, das jeder Softwareentwickler unbedingt
positiv über
4
Absolut brilliant. Klar und leicht zu verstehen. Ich möchte jedoch erwähnen, dass diese Zeile - "Wenn Sie sie drucken, wird Python sie als b'I am a string 'darstellen" für Python3 gilt, da für Python2-Bytes und str dasselbe sind.
SRC
5
Ich vergebe Ihnen dieses Kopfgeld dafür, dass Sie eine sehr gut lesbare Erklärung anbieten, um diesem Thema Klarheit zu verleihen!
Fedorqui 'SO hör auf zu schaden'
3
Gute Antwort. Das Einzige, was vielleicht hinzugefügt werden könnte, ist, deutlicher darauf hinzuweisen, dass Programmierer und Programmiersprachen in der Vergangenheit explizit oder implizit davon ausgegangen sind, dass eine Bytesequenz und eine ASCII-Zeichenfolge dasselbe waren . Python 3 hat beschlossen, diese Annahme meiner Meinung nach explizit zu brechen.
nekomatisch
4
Link zu Joels Beitrag, der oben von @ neil.millikin erwähnt wurde: joelonsoftware.com/2003/10/08/…
Kshitij Saraogi
14

Hinweis: Ich werde meine Antwort für Python 3 näher erläutern, da das Lebensende von Python 2 sehr nahe ist.

In Python 3

bytesbesteht aus Sequenzen von vorzeichenlosen 8-Bit-Werten, während es straus Sequenzen von Unicode-Codepunkten besteht, die Textzeichen aus menschlichen Sprachen darstellen.

>>> # bytes
>>> b = b'h\x65llo'
>>> type(b)
<class 'bytes'>
>>> list(b)
[104, 101, 108, 108, 111]
>>> print(b)
b'hello'
>>>
>>> # str
>>> s = 'nai\u0308ve'
>>> type(s)
<class 'str'>
>>> list(s)
['n', 'a', 'i', '̈', 'v', 'e']
>>> print(s)
naïve

Obwohl bytesund strscheinen auf die gleiche Weise zu funktionieren, sind ihre Instanzen nicht miteinander kompatibel, dh bytesund strInstanzen können nicht zusammen mit Operatoren wie >und verwendet werden +. Beachten Sie außerdem, dass Vergleiche bytesund strInstanzen für Gleichheit, dh Verwenden ==, immer ausgewertet werden, Falseauch wenn sie genau dieselben Zeichen enthalten.

>>> # concatenation
>>> b'hi' + b'bye' # this is possible
b'hibye'
>>> 'hi' + 'bye' # this is also possible
'hibye'
>>> b'hi' + 'bye' # this will fail
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't concat str to bytes
>>> 'hi' + b'bye' # this will also fail
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "bytes") to str
>>>
>>> # comparison
>>> b'red' > b'blue' # this is possible
True
>>> 'red'> 'blue' # this is also possible
True
>>> b'red' > 'blue' # you can't compare bytes with str
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '>' not supported between instances of 'bytes' and 'str'
>>> 'red' > b'blue' # you can't compare str with bytes
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '>' not supported between instances of 'str' and 'bytes'
>>> b'blue' == 'red' # equality between str and bytes always evaluates to False
False
>>> b'blue' == 'blue' # equality between str and bytes always evaluates to False
False

Ein weiteres Problem beim Umgang mit bytesund strbei der Arbeit mit Dateien, die mit dem zurückgegeben werdenopen integrierten Funktion zurückgegeben werden. Wenn Sie einerseits Binärdaten in / aus einer Datei lesen oder schreiben möchten, öffnen Sie die Datei immer in einem Binärmodus wie 'rb' oder 'wb'. Wenn Sie andererseits Unicode-Daten in / aus einer Datei lesen oder schreiben möchten, beachten Sie die Standardcodierung Ihres Computers. Übergeben Sie daher gegebenenfalls den encodingParameter, um Überraschungen zu vermeiden.

In Python 2

strbesteht aus Sequenzen von 8-Bit-Werten, während es unicodeaus Sequenzen von Unicode-Zeichen besteht. Eine Sache zu beachten ist, dass strund unicodekann zusammen mit Bedienern verwendet werden, wennstr nur besteht aus 7-Bit - ASCI Zeichen.

Es kann nützlich sein, Hilfsfunktionen zum Konvertieren zwischen strund unicodein Python 2 sowie zwischen bytesund strin Python 3 zu verwenden.

lmiguelvargasf
quelle
4

Aus Was ist Unicode :

Grundsätzlich beschäftigen sich Computer nur mit Zahlen. Sie speichern Buchstaben und andere Zeichen, indem sie jedem eine Nummer zuweisen.

......

Unicode bietet eine eindeutige Nummer für jedes Zeichen, unabhängig von der Plattform, unabhängig vom Programm und der Sprache.

Wenn ein Computer eine Zeichenfolge darstellt, findet er Zeichen, die im Computer der Zeichenfolge gespeichert sind, anhand ihrer eindeutigen Unicode-Nummer, und diese Zahlen werden im Speicher gespeichert. Sie können die Zeichenfolge jedoch nicht direkt auf die Festplatte schreiben oder über ihre eindeutige Unicode-Nummer im Netzwerk übertragen, da es sich bei diesen Zahlen nur um einfache Dezimalzahlen handelt. Sie sollten die Zeichenfolge in eine Bytezeichenfolge codieren, z UTF-8. UTF-8ist eine Zeichenkodierung, die alle möglichen Zeichen kodieren kann und Zeichen als Bytes speichert (es sieht so ). Die codierte Zeichenfolge kann also überall verwendet werden, da sie UTF-8fast überall unterstützt wird. Wenn Sie eine in codierte Textdatei öffnenUTF-8Von anderen Systemen dekodiert Ihr Computer es und zeigt die darin enthaltenen Zeichen anhand ihrer eindeutigen Unicode-Nummer an. Wenn ein Browser UTF-8vom Netzwerk codierte Zeichenfolgendaten empfängt , dekodiert er die Daten in Zeichenfolgen (vorausgesetzt, der Browser UTF-8codiert) und zeigt die Zeichenfolge an.

In Python3 können Sie Zeichenfolge und Byte-Zeichenfolge ineinander umwandeln:

>>> print('中文'.encode('utf-8'))
b'\xe4\xb8\xad\xe6\x96\x87'
>>> print(b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8'))
中文 

Mit einem Wort, Zeichenfolge dient zum Anzeigen für Menschen zum Lesen auf einem Computer und Byte-Zeichenfolge zum Speichern auf Festplatte und zur Datenübertragung.

Sam Yang
quelle
1

Unicode ist ein vereinbartes Format für die binäre Darstellung von Zeichen und verschiedene Arten der Formatierung (z. B. Klein- / Großbuchstaben, neue Zeile, Wagenrücklauf) und andere "Dinge" (z. B. Emojis). Ein Computer ist nicht weniger in der Lage, eine Unicode-Darstellung (eine Reihe von Bits) im Speicher oder in einer Datei zu speichern, als eine ASCII-Darstellung (eine andere Reihe von Bits) oder eine andere Darstellung (Reihe von Bits) zu speichern ).

Damit die Kommunikation stattfinden kann, müssen die Parteien der Kommunikation vereinbaren, welche Vertretung verwendet wird.

Weil Unicode versucht, alle darzustellen möglichen Zeichen (und andere "Dinge") die in der Kommunikation zwischen Mensch und Computer verwendet werden, erfordert es eine größere Anzahl von Bits für die Darstellung vieler Zeichen (oder Dinge) als andere Darstellungssysteme, die versuchen, eine begrenzte Anzahl von Charakteren / Dingen darzustellen. Zur "Vereinfachung" und möglicherweise zur Berücksichtigung der historischen Verwendung wird die Unicode-Darstellung fast ausschließlich in ein anderes Darstellungssystem (z. B. ASCII) konvertiert, um Zeichen in Dateien zu speichern.

Es ist nicht der Fall , die Unicode kann nicht zum Speichern von Zeichen in Dateien verwendet werden, oder sie durch Übertragung von jedem Kommunikationskanal, einfach , dass es ist nicht.

Der Begriff "Zeichenfolge" ist nicht genau definiert. "String" bezieht sich im allgemeinen Sprachgebrauch auf eine Reihe von Zeichen / Dingen. In einem Computer können diese Zeichen in einer von vielen verschiedenen bitweisen Darstellungen gespeichert werden. Eine "Byte-Zeichenfolge" ist ein Satz von Zeichen, die unter Verwendung einer Darstellung gespeichert werden, die acht Bits verwendet (acht Bits werden als Byte bezeichnet). Da Computer heutzutage das Unicode-System (Zeichen, die durch eine variable Anzahl von Bytes dargestellt werden) zum Speichern von Zeichen im Speicher und Byte-Zeichenfolgen (Zeichen, die durch einzelne Bytes dargestellt werden) zum Speichern von Zeichen in Dateien verwenden, muss vor den dargestellten Zeichen eine Konvertierung verwendet werden im Speicher wird in Dateien gespeichert.

Gordon Shephard
quelle
0

Lassen Sie uns eine einfache Zeichenfolge mit einem Zeichen haben 'š'und sie in eine Folge von Bytes codieren:

>>> 'š'.encode('utf-8')
b'\xc5\xa1'

In diesem Beispiel zeigen wir die Folge von Bytes in ihrer binären Form an:

>>> bin(int(b'\xc5\xa1'.hex(), 16))
'0b1100010110100001'

Jetzt ist es im Allgemeinen nicht möglich , die Informationen zurück zu decodieren, ohne zu wissen, wie sie codiert wurden. Nur wenn Sie wissen, dass die utf-8Textcodierung verwendet wurde, können Sie dem Algorithmus zum Decodieren von utf-8 folgen und die ursprüngliche Zeichenfolge abrufen :

11000101 10100001
   ^^^^^   ^^^^^^
   00101   100001

Sie können die Binärzahl 101100001wieder als Zeichenfolge anzeigen :

>>> chr(int('101100001', 2))
'š'
Jeyekomon
quelle
0

Die Python-Sprachen enthalten strund bytesstandardmäßig "Integrierte Typen". Mit anderen Worten, sie sind beide Klassen. Ich denke nicht, dass es sich lohnt zu erklären, warum Python auf diese Weise implementiert wurde.

Trotzdem strund bytessind einander sehr ähnlich. Beide teilen die meisten der gleichen Methoden. Die folgenden Methoden sind für die strKlasse einzigartig :

casefold
encode
format
format_map
isdecimal
isidentifier
isnumeric
isprintable

Die folgenden Methoden sind für die bytesKlasse einzigartig :

decode
fromhex
hex
fünfzig Karten
quelle