Відповіді:
Якщо припустити Python 3 (у Python 2 ця різниця трохи менш чітко визначена) - рядок - це послідовність символів, тобто кодові точки unicode ; це абстрактне поняття, яке не може бути безпосередньо збережено на диску. Рядок байтів - це послідовність, не дивно, байтів - речей, які можна зберігати на диску. Відображення між ними є кодуванням - їх дуже багато (і нескінченно багато можливих) - і вам потрібно знати, що застосовується в конкретному випадку для здійснення перетворення, оскільки інше кодування може відображати однакові байти до іншого рядка:
>>> 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ς'
Після того, як ви дізнаєтеся, який з них використовувати, ви можете скористатися .decode()
методом байтового рядка, щоб отримати потрібну рядок символів з нього, як зазначено вище. Для повноти .encode()
метод рядка символів йде навпаки:
>>> 'τoρνoς'.encode('utf-8')
b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82'
str
не є доступним або релевантним з боку Python; структура даних - це лише послідовність кодових точок. Відповідно до PEP 393 , точне внутрішнє кодування є латинським-1, UCS2 або UCS4, і представлення utf-8 може бути кешоване після його першого запиту, але навіть C-код відмовляється покладатися на ці внутрішні деталі.
Єдине, що може зберігати комп’ютер, - це байти.
Щоб зберігати що-небудь у комп’ютері, спершу його потрібно закодувати , тобто перетворити в байти. Наприклад:
MP3
, WAV
і т.д.PNG
, JPEG
і т.д.ASCII
, UTF-8
і т.д.MP3
, WAV
, PNG
, JPEG
, ASCII
І UTF-8
приклади кодування . Кодування - це формат для представлення звуку, зображень, тексту тощо в байтах.
У Python рядок байтів - це саме те, що: послідовність байтів. Це не читабельно для людей. Під кришкою все повинно бути перетворено в рядок байтів, щоб воно могло зберігатися в комп'ютері.
З іншого боку, символьний рядок, який часто називають "рядком", - це послідовність символів. Це читається людиною. Рядок символів не може бути безпосередньо збережений у комп'ютері, його потрібно спочатку закодувати (перетворити в рядок байтів). Існує кілька кодувань, за допомогою яких символьна рядок може бути перетворена в рядок байтів, таких як ASCII
і UTF-8
.
'I am a string'.encode('ASCII')
Вищенаведений код Python буде кодувати рядок 'I am a string'
за допомогою кодування ASCII
. Результатом вищевказаного коду стане рядок байтів. Якщо ви надрукуєте його, Python буде представляти його як b'I am a string'
. Пам’ятайте, однак, що байтові рядки не читаються людиною , це лише те, що Python розшифровує їх, ASCII
коли ви їх друкуєте. У Python рядок байтів представлений символом a b
, а потім представленням рядка байтів ASCII
.
Рядок байтів може бути декодований назад в символьну рядок, якщо ви знаєте кодування, яке було використано для його кодування.
b'I am a string'.decode('ASCII')
Вищевказаний код поверне початковий рядок 'I am a string'
.
Кодування та декодування - це зворотні операції. Все має бути закодовано, перш ніж його можна записати на диск, і його треба розшифрувати, перш ніж людина може його прочитати.
Примітка: Я детальніше розробимо свою відповідь на Python 3, оскільки кінець життя Python 2 дуже близький.
У Python 3
bytes
складається з послідовностей 8-бітних неподписаних значень, тоді як str
складається з послідовностей кодових точок Unicode, які представляють текстові символи з людських мов.
>>> # 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
Незважаючи на те, bytes
і str
здається, працюють точно так же, їх екземпляри не сумісні один з одним, тобто bytes
і str
екземпляри не можуть бути використані разом з операторами , як >
і +
. Крім того, майте на увазі, що порівняння bytes
та str
випадки рівності, тобто використання ==
, завжди оцінюватимуть False
навіть тоді, коли вони містять абсолютно однакові символи.
>>> # 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
Ще одне питання при роботі bytes
і str
є при роботі з файлами, які повертаються за допомогою open
вбудованої функції. З одного боку, якщо ви хочете читати або записувати бінарні дані в / з файлу, завжди відкривайте файл у двійковому режимі, наприклад 'rb' або 'wb'. З іншого боку, якщо ви хочете прочитати або записати дані Unicode у файл / з файлу, пам’ятайте про кодування за замовчуванням вашого комп’ютера, тому при необхідності передайте encoding
параметр, щоб уникнути сюрпризів.
У Python 2
str
складається з послідовностей 8-бітних значень, тоді як unicode
складається з послідовностей символів Unicode. Одна річ , щоб мати на увазі, що str
і unicode
може бути використано разом з операторами , якщо str
складається тільки з 7-бітових символів ASCI.
Можливо, буде корисно використовувати допоміжні функції для перетворення між str
і unicode
в Python 2, і між bytes
і str
в Python 3.
З Що таке Unicode :
Принципово, комп'ютери просто мають справу з цифрами. Вони зберігають букви та інші символи, присвоюючи номер кожному.
......
Unicode надає унікальний номер для кожного символу, незалежно від платформи, незалежно від програми, незалежно від мови.
Отже, коли комп'ютер представляє рядок, він знаходить символи, що зберігаються в комп'ютері рядка через їх унікальний номер Unicode, і ці фігури зберігаються в пам'яті. Але ви не можете безпосередньо записати рядок на диск або передати рядок в мережі через їх унікальний номер Unicode, оскільки ці цифри - це просто просте десяткове число. Ви повинні кодувати рядок до байтового рядка, наприклад UTF-8
. UTF-8
це символ , який кодує здатними кодувати всі можливі символи і зберігає символи , як байти (це виглядає як це ). Тож закодована рядок може використовуватися скрізь, оскільки UTF-8
майже підтримується скрізь. Коли ви відкриєте закодований текстовий файлUTF-8
в інших системах ваш комп'ютер буде декодувати його та відображати символи в ньому через унікальний номер Unicode. Коли браузер отримує рядкові дані, закодовані UTF-8
з мережі, він декодує дані в рядкові (припустимо браузер в UTF-8
кодуванні) і відображає рядок.
У python3 ви можете перетворити рядок і рядок байтів один в одного:
>>> print('中文'.encode('utf-8'))
b'\xe4\xb8\xad\xe6\x96\x87'
>>> print(b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8'))
中文
Словом, рядок призначений для відображення людям для читання на комп’ютері, а байтовий рядок - для зберігання на диску та передачі даних.
Unicode - це узгоджений формат для двійкового представлення символів та різного роду форматування (наприклад, нижній регістр / верхній регістр, нова лінія, повернення каретки) та інші "речі" (наприклад, емоджи). Комп'ютер не менш здатний зберігати представлення unicode (серія біт), чи в пам'яті, чи у файлі, ніж це для зберігання представлення ascii (інша серія біт) або будь-яке інше представлення (серія біт) ).
Для того, щоб спілкування відбулося, сторони спілкування повинні домовитись про те, яке представництво буде використовуватися.
Оскільки unicode прагне представити всі можливі символи (та інші "речі"), що використовуються в спілкуванні між людьми та між комп'ютерами, для представлення багатьох символів (або речей) потрібна більша кількість бітів, ніж інші системи представлення, які прагнути представити більш обмежений набір символів / речей. Для "спрощення" та, можливо, для історичного використання, представлення unicode майже виключно перетворюється на якусь іншу систему подання (наприклад, ascii) з метою зберігання символів у файлах.
Це не той випадок, юнікод не може бути використаний для зберігання символів в файлах, або передавати їх через будь-який канал зв'язку, просто , що це НЕ так .
Термін "рядок" точно не визначений. "Рядок" у своєму загальному використанні відноситься до набору символів / речей. На комп'ютері ці символи можуть зберігатися в будь-якому з багатьох різних побітових зображень. "Рядок байтів" - це набір символів, що зберігається за допомогою представлення, яке використовує вісім біт (вісім біт називають байтом). Оскільки в ці дні комп’ютери використовують систему Unicode (символи, представлені змінною кількістю байтів) для зберігання символів у пам'яті, а рядки байтів (символи, представлені одиничними байтами) для зберігання символів у файлах, перетворення повинно використовуватися перед тим, як символи представлені в пам'яті буде переміщено в сховище у файлах.
Будемо мати простий односимвольний рядок 'š'
і кодувати його в послідовності байтів:
>>> 'š'.encode('utf-8')
b'\xc5\xa1'
Для цього прикладу покажемо послідовність байтів у його двійковому вигляді:
>>> bin(int(b'\xc5\xa1'.hex(), 16))
'0b1100010110100001'
Зараз взагалі неможливо декодувати інформацію назад, не знаючи, як вона була закодована. Тільки якщо ви знаєте, що використовувалося utf-8
кодування тексту, ви можете слідувати алгоритму розшифровки utf-8 та отримати початковий рядок:
11000101 10100001
^^^^^ ^^^^^^
00101 100001
Ви можете відображати бінарне число 101100001
назад як рядок:
>>> chr(int('101100001', 2))
'š'
Мова Python включає str
і bytes
як "Вбудовані типи" як стандарт. Іншими словами, вони обидва класи. Я не думаю, що варто намагатися раціоналізувати, чому Python реалізований таким чином.
Сказавши це, str
і bytes
дуже схожі між собою. Обидва поділяють більшість однакових методів. Наступні методи унікальні для str
класу:
casefold
encode
format
format_map
isdecimal
isidentifier
isnumeric
isprintable
Наступні методи унікальні для bytes
класу:
decode
fromhex
hex
str
тип такий же, якbytes
тип; ця відповідь рівномірно порівнюєunicode
тип (не існує в Python 3) зstr
типом.