Python2: что делают str.encode () и unicode.decode ()? - PullRequest
1 голос
/ 18 марта 2020

Из этого вопроса и его ответов Python str против типов Unicode Я понял, что unicode.encode() дает вам str, а str.decode() дает вам unicode:

a = 'à'
ua = u'à'
print type(a)  # str
print type(ua)  # unicode
print ua.encode('utf-8') == a  # True
print a.decode('utf-8') == ua  # True

Но я не понимаю цели методов unicode.decode() и str.encode(). Что они должны вернуть? Как я могу их использовать? Обе следующие строки не работают с UnicodeDecodeError или UnicodeEncodeError:

print ua.decode('utf-8')
print a.encode('utf-8')

1 Ответ

2 голосов
/ 18 марта 2020

TL; DR Использование unicode.decode и str.encode означает, что вы не используете правильные типы для представления своих данных. Методы в эквивалентных типах в Python 3 даже не существуют.


A unicode значение представляет собой одну кодовую точку Unicode: целое число интерпретируется как особый персонаж. A str, с другой стороны, представляет собой последовательность байтов.

Например, à - это кодовая точка Unicode U + 00E0. Кодировка UTF-8 представляет его с помощью пары байтов, 0xC3 и 0xA0.

Метод unicode.encode принимает строку Unicode (последовательность кодовых точек) и возвращает байтовый код. кодирование уровня каждой кодовой точки в виде одной строки байтов.

>>> ua.encode('utf-8')
'\xc3\xa0'

str.decode принимает строку байтов и пытается создать эквивалентное значение Unicode.

>>> '\xc3\xa0'.decode('utf-8')
u'\xe0'

(u'\xe0' эквивалентно u'à').


Что касается ваших ошибок: Python 2 не требует строгого разделения между использованием unicode и str. На самом деле не имеет смысла смысл кодировать str, если это уже закодированное значение, и нет смысла декодировать значение unicode, потому что оно не закодировано в первую очередь. Вместо того, чтобы точно определять, как происходят ошибки, я просто укажу, что в Python 3 есть два типа: bytes - строка байтов (соответствует Python 2 str) и str является строкой Unicode (соответствует Python 2 unicode). «Бессмысленные» методы даже не существуют в Python 3:

>>> bytes.encode
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'bytes' has no attribute 'encode'
>>> str.decode
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'str' has no attribute 'decode'

Так что ваши попытки, которые раньше вызывали Unicode*Error исключений, просто подняли бы AttributeError.

Если вы застряли с поддержкой Python 2, просто следуйте этим правилам:

  • unicode для текст
  • str для двоичных данных
  • unicode.encode выдает str значение
  • str.decode выдает unicode значение
  • Если вы пытаетесь вызвать str.encode, вы используете неправильный тип.
  • Если вы пытаетесь позвонить unicode.decode, вы используете неправильный тип.
...