#python #unpack
Вопрос:
Я пытаюсь получить первый символ байтовой строки в python 3.4, но когда я его индексирую, я получаю int
:
>>> my_bytes = b'just a byte string'
b'just a byte string'
>>> my_bytes[0]
106
>>> type(my_bytes[0])
<class 'int'>
Мне это кажется неинтуитивным, как я и ожидал b'j'
.
Я обнаружил, что могу получить ту ценность, которую ожидаю, но для меня это похоже на взлом.
>>> my_bytes[0:1]
b'j'
Может кто-нибудь, пожалуйста, объяснить, почему это происходит?
Комментарии:
1. Взлом с использованием такого диапазона
my_bytes[0:1]
действительно помог мне написать код, совместимый с Python2/Python3. Я хотел бы увидеть ответ, который охватывает наилучшую практику для совместимого кода, решающего эту проблему. Например:ord(my_bytes[0])
дает int в Python2, ноmy_bytes[0]
дает int в Python3. Чтобы работать в обоих, я используюord(my_bytes[0:1])
то, что кажется действительно уродливым для Python3.2. ваш ответ помог мне, я не смог найти наилучшего подхода к работе с байтами и избежать преобразования целых чисел при доступе к индексу, спасибо.
3. Я заметил те же явления со списками, составленными из bytearray и bytestring.
type(list(b'abctest').pop(0))
дать<class 'int'>
.type(list(bytearray(b'abctest')).pop(0))
дать<class 'int'>
.type(bytearray(b'abctest').pop(0))
дать<class 'int'>
.
Ответ №1:
Тип является bytes
типом двоичной последовательности и явно задокументирован как содержащий последовательность целых чисел в диапазоне от 0 до 255.
Из документации:
Объекты Bytes-это неизменяемые последовательности отдельных байтов.
[…]
В то время как байтовые литералы и представления основаны на тексте ASCII, байтовые объекты фактически ведут себя как неизменяемые последовательности целых чисел, при этом каждое значение в последовательности ограничено таким образом, что
0 <= x < 256
[.][…]
Поскольку объекты bytes являются последовательностями целых чисел (сродни кортежу), для объекта bytes
b
b[0]
будет целым числом , в то времяb[0:1]
как будетbytes
объектом длины 1. (Это контрастирует с текстовыми строками, где как индексирование, так и нарезка приведут к строке длиной 1).
Смелый акцент мой. Обратите внимание, что индексирование строки является небольшим исключением среди типов последовательностей; 'abc'[0]
дает вам str
объект длиной один; str
является единственным типом последовательности, который всегда содержит элементы своего собственного типа.
Это перекликается с тем, как другие языки обрабатывают строковые данные; в C unsigned char
тип также фактически является целым числом в диапазоне 0-255. Многие компиляторы языка Си по умолчанию unsigned
используют, если вы используете неквалифицированный char
тип, а текст моделируется как char[]
массив.
Комментарии:
1. «в то время как b[0:1] будет байтовым объектом длиной 1(это контрастирует с текстовыми строками, где как индексирование, так и нарезка приведут к строке длиной 1)»не могли бы вы, пожалуйста, объяснить это предложение, которое я не понял?
2. @CY5: извините, какую часть вы получили? Если вы создадите строку (в Юникоде),
'abc'[0]'
будет создан другой строковый объект'a'
. Если вы используете тот же срез, что и в примере, используемом дляbytes
объекта,'abc'[0:1]
также создается строковый объект длиной один,'a'
.3. @CY5: но для
bytes
объектаb'abc'[0]
создается целое число (97
), а нарезка создаетbytes
объект длиной один (b'abc'[0:1]
производитb'a'
).