Python 2 против 3: согласованные результаты с получением байта из байтовой строки - PullRequest
2 голосов
/ 16 октября 2019

Есть ли какой-нибудь простой способ получить согласованные результаты как в Python 2, так и в Python 3 для операции, например "дать мне N-й байт в строке байтов"? Подойдёт либо байт-как-целое число, так и байт-как-символ, если это будет согласованно.

Т.е. при

s = b"123"

Наивный подход дает:

s[1] # => Python 2: '2', <type 'str'>
s[1] # => Python 3: 50, <class 'int'>

Обтекание, которое в ord(...) приводит к ошибке в Python 3:

ord(s[1]) # => Python 2: 50, <type 'int'> 
ord(s[1]) # => Python 3: TypeError: ord() expected string of length 1, but int found

Я могу придумать довольно сложное совместное решение:

ord(s[1]) if (type(s[1]) == type("str")) else s[1] # 50 in both Python 2 and 3

... но может быть, есть более простой способ, который я просто не замечаю?

Ответы [ 3 ]

3 голосов
/ 16 октября 2019

Срез длины 1 также будет байтовой последовательностью в 2.x или 3.x:

s = b'123'
s[1:2] # 3.x: b'2'; 2.x: '2', which is the same thing but the repr() rules are different.
2 голосов
/ 16 октября 2019

Если вы используете (при необходимости конвертируете) тип bytearray, поведение будет одинаковым в обеих версиях, всегда совпадая с поведением Python 3 bytes. Это потому, что bytearray на самом деле является отдельным типом в Python 2 (с поведением Python 3), где bytes - это просто псевдоним для str.

Более типичным решением было бы использование six библиотека совместимости, которая обеспечивает six.indexbytes, поэтому в любой версии Python вы можете сделать:

>>> six.indexbytes(s, 1)
50
0 голосов
/ 16 октября 2019

А как насчет этого?

import sys

if sys.version_info.major == 3:
    def index(s, n):
        return s[n]
elif sys.version_info.major == 2:
    def index(s, n):
        return ord(s[n])
else:
    raise NotImplementedError
...