Odpowiedzi:
Zakładając, że Python 3 (w Pythonie 2 ta różnica jest nieco mniej dobrze zdefiniowana) - ciąg znaków jest sekwencją znaków, tj. Punktami kodowymi Unicode ; są to abstrakcyjne pojęcia i nie mogą być bezpośrednio przechowywane na dysku. Ciąg bajtów to sekwencja bajtów - rzeczy, które można przechowywać na dysku. Mapowanie między nimi jest kodowaniem - jest ich całkiem sporo (i nieskończenie wiele jest możliwych) - i musisz wiedzieć, które mają zastosowanie w danym przypadku, aby wykonać konwersję, ponieważ inne kodowanie może odwzorować te same bajty do innego ciągu:
>>> 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ς'
Kiedy już wiesz, którego użyć, możesz użyć .decode()
metody ciągu bajtów, aby uzyskać z niego odpowiedni ciąg znaków, jak wyżej. Dla kompletności .encode()
metoda ciągu znaków przebiega w drugą stronę:
>>> 'τoρνoς'.encode('utf-8')
b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82'
str
nie jest dostępna ani istotna ze strony Pythona; struktura danych jest tylko sekwencją punktów kodowych. Zgodnie z PEP 393 , dokładne kodowanie wewnętrzne to Latin-1, UCS2 lub UCS4, a reprezentacja utf-8 może być buforowana po pierwszym żądaniu, ale nawet kod C nie jest zależny od tych wewnętrznych szczegółów.
Jedyne, co komputer może przechowywać, to bajty.
Aby zapisać cokolwiek w komputerze, musisz najpierw go zakodować , tzn. Przekonwertować na bajty. Na przykład:
MP3
, WAV
itdPNG
, JPEG
itdASCII
, UTF-8
itdMP3
, WAV
, PNG
, JPEG
, ASCII
I UTF-8
przedstawiono przykłady kodowania . Kodowanie to format reprezentujący audio, obrazy, tekst itp. W bajtach.
W Pythonie ciąg bajtów jest po prostu: sekwencją bajtów. Nie jest czytelny dla człowieka. Pod maską wszystko musi zostać przekonwertowane na ciąg bajtów, zanim będzie można je zapisać na komputerze.
Z drugiej strony ciąg znaków, często nazywany po prostu „ciągiem”, jest ciągiem znaków. Jest czytelny dla człowieka. Ciąg znaków nie może być bezpośrednio zapisany na komputerze, musi być najpierw zakodowany (przekształcony w ciąg bajtów). Istnieje wiele kodowań, za pomocą których ciąg znaków można przekonwertować na ciąg bajtów, takich jak ASCII
i UTF-8
.
'I am a string'.encode('ASCII')
Powyższy kod Python koduje ciąg 'I am a string'
przy użyciu kodowania ASCII
. Wynikiem powyższego kodu będzie ciąg bajtów. Jeśli go wydrukujesz, Python będzie go reprezentował jako b'I am a string'
. Pamiętaj jednak, że ciągi bajtów nie są czytelne dla człowieka , po prostu Python dekoduje je ASCII
podczas drukowania. W Pythonie ciąg bajtów jest reprezentowany przez a b
, po którym następuje reprezentacja ciągu bajtów ASCII
.
Łańcuch bajtów może zostać zdekodowany z powrotem na ciąg znaków, jeśli znasz kodowanie użyte do jego zakodowania.
b'I am a string'.decode('ASCII')
Powyższy kod zwróci oryginalny ciąg 'I am a string'
.
Kodowanie i dekodowanie to operacje odwrotne. Wszystko musi zostać zakodowane, zanim będzie mogło zostać zapisane na dysk, i musi zostać odkodowane, zanim będzie mogło być odczytane przez człowieka.
Uwaga: Bardziej szczegółowo opracuję moją odpowiedź dla Python 3, ponieważ koniec życia Python 2 jest bardzo bliski.
W Python 3
bytes
składa się z sekwencji 8-bitowych wartości bez znaku, natomiast str
składa się z sekwencji punktów kodu Unicode reprezentujących znaki tekstowe z języków ludzkich.
>>> # 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
Mimo że bytes
i str
wydają się działać w ten sam sposób, ich instancje nie są ze sobą kompatybilne, tj. bytes
I str
instancji nie można używać razem z operatorami takimi jak >
i +
. Ponadto należy pamiętać, że porównywanie bytes
i str
przypadki równości, tj. Używanie ==
, zawsze będą oceniać, False
nawet jeśli zawierają dokładnie te same znaki.
>>> # 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
Kolejny problem związany z obsługą bytes
i str
występujący podczas pracy z plikami zwracanymi za pomocą open
wbudowanej funkcji. Z jednej strony, jeśli chcesz czytać lub zapisywać dane binarne do / z pliku, zawsze otwieraj plik w trybie binarnym, takim jak „rb” lub „wb”. Z drugiej strony, jeśli chcesz czytać lub zapisywać dane Unicode do / z pliku, pamiętaj o domyślnym kodowaniu komputera, więc w razie potrzeby przekaż encoding
parametr, aby uniknąć niespodzianek.
W Python 2
str
składa się z sekwencji 8-bitowych wartości, a unicode
składa się z sekwencji znaków Unicode. Należy pamiętać o tym str
i unicode
można go używać razem z operatorami, jeśli str
składa się tylko z 7-bitowych znaków ASCI.
Przydatne może być użycie funkcji pomocniczych do konwersji pomiędzy str
i unicode
w Pythonie 2 oraz pomiędzy bytes
i str
w Pythonie 3.
Zasadniczo komputery zajmują się tylko liczbami. Przechowują litery i inne znaki, przypisując każdemu numer.
......
Unicode zapewnia unikalny numer dla każdego znaku, bez względu na platformę, bez względu na program, bez względu na język.
Kiedy więc komputer reprezentuje ciąg znaków, znajduje znaki zapisane na komputerze ciągu dzięki unikalnemu numerowi Unicode, a liczby te są przechowywane w pamięci. Ale nie można bezpośrednio napisać łańcucha na dysk ani przesłać go w sieci za pomocą jego unikalnego numeru Unicode, ponieważ liczby te są po prostu zwykłą liczbą dziesiętną. Należy zakodować ciąg do ciągu bajtowego, na przykład UTF-8
. UTF-8
to postać kodowania zdolne do kodowania wszystkich możliwych znaków i przechowuje znaki jako bajty (wygląda jak ten ). Tak więc zakodowany ciąg może być używany wszędzie, ponieważ UTF-8
jest prawie wszędzie obsługiwany. Po otwarciu pliku tekstowego zakodowanego wUTF-8
z innych systemów komputer go dekoduje i wyświetla w nim znaki za pomocą unikalnego numeru Unicode. Gdy przeglądarka odbiera dane łańcucha zakodowane UTF-8
z sieci, dekoduje dane do łańcucha (zakładając, że przeglądarka UTF-8
koduje) i wyświetla ciąg.
W python3 możesz transformować ciąg znaków i bajtów na siebie:
>>> print('中文'.encode('utf-8'))
b'\xe4\xb8\xad\xe6\x96\x87'
>>> print(b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8'))
中文
Jednym słowem, ciąg znaków służy do wyświetlania ludziom do odczytu na komputerze, a ciąg bajtów służy do przechowywania na dysku i transmisji danych.
Unicode jest uzgodnionym formatem binarnej reprezentacji znaków i różnego rodzaju formatowania (np. Małe / wielkie litery, nowa linia, znak powrotu karetki) i innych „rzeczy” (np. Emoji). Komputer jest nie mniej zdolny do przechowywania reprezentacji Unicode (seria bitów), czy to w pamięci, czy w pliku, niż do przechowywania reprezentacji ascii (inna seria bitów) lub jakiejkolwiek innej reprezentacji (seria bitów ).
Aby komunikacja mogła się odbyć, strony komunikacji muszą uzgodnić, jaką reprezentację należy zastosować.
Ponieważ Unicode stara się reprezentować wszystkie możliwe znaki (i inne „rzeczy”) używane w komunikacji między ludźmi i między komputerami, wymaga większej liczby bitów do przedstawienia wielu znaków (lub rzeczy) niż inne systemy reprezentacji, które starają się reprezentować bardziej ograniczony zestaw znaków / rzeczy. Aby „uprościć” i być może dostosować do użycia w przeszłości, reprezentacja Unicode jest prawie wyłącznie konwertowana na inny system reprezentacji (np. Ascii) w celu przechowywania znaków w plikach.
Nie jest tak, że Unicode nie może być używane do przechowywania znaków w plikach lub przesyłania ich jakimkolwiek kanałem komunikacyjnym, po prostu tak nie jest .
Termin „ciąg znaków” nie jest dokładnie zdefiniowany. „Ciąg znaków” w swoim powszechnym użyciu odnosi się do zestawu znaków / rzeczy. Na komputerze znaki te mogą być przechowywane w dowolnej z wielu różnych reprezentacji krok po kroku. „Łańcuch bajtów” to zestaw znaków przechowywanych przy użyciu reprezentacji, która wykorzystuje osiem bitów (osiem bitów nazywanych jest bajtem). Ponieważ w dzisiejszych czasach komputery używają systemu Unicode (znaki reprezentowane przez zmienną liczbę bajtów) do przechowywania znaków w pamięci, a ciągi bajtów (znaki reprezentowane przez pojedyncze bajty) do przechowywania znaków w plikach, należy zastosować konwersję przed znakami reprezentowanymi w pamięci zostaną przeniesione do przechowywania w plikach.
Miejmy prosty jednoznakowy ciąg 'š'
i zakodujemy go w sekwencji bajtów:
>>> 'š'.encode('utf-8')
b'\xc5\xa1'
Na potrzeby tego przykładu wyświetlmy sekwencję bajtów w postaci binarnej:
>>> bin(int(b'\xc5\xa1'.hex(), 16))
'0b1100010110100001'
Teraz generalnie nie jest możliwe odkodowanie informacji bez wiedzy, w jaki sposób została zakodowana. Tylko jeśli wiesz, że zastosowano utf-8
kodowanie tekstu, możesz postępować zgodnie z algorytmem dekodowania utf-8 i uzyskać oryginalny ciąg znaków:
11000101 10100001
^^^^^ ^^^^^^
00101 100001
Możesz wyświetlić liczbę binarną z 101100001
powrotem jako ciąg:
>>> chr(int('101100001', 2))
'š'
Języki Python obejmują str
i bytes
jako standardowe „typy wbudowane”. Innymi słowy, obie są klasami. Nie sądzę, że warto próbować zracjonalizować, dlaczego Python został wdrożony w ten sposób.
Mimo, że str
i bytes
są bardzo podobne do siebie. Oba korzystają z większości tych samych metod. Następujące metody są unikalne dla tej str
klasy:
casefold
encode
format
format_map
isdecimal
isidentifier
isnumeric
isprintable
Następujące metody są unikalne dla tej bytes
klasy:
decode
fromhex
hex
str
typ jest taki sam jakbytes
typ; ta odpowiedź w sposób równoważny porównujeunicode
typ (nie istnieje w Pythonie 3) zstr
typem.