Python: данные против текста?

Презентация Guido van Rossum о Python 3000 упоминает несколько вещей, чтобы в конечном итоге перейти от Python 2 к Python 3. Он специально говорит о обработке текста с момента перехода на Unicode, поскольку единственное представление строк в Python 3 является одним из основных изменений.

Что касается обработки текста, один слайд (# 14) говорит:

  • В версии 2.6:
    • Используйте байты и b '...' для всех данных (зная, что это просто псевдонимы для str и "..." )
    • Используйте unicode и u '...' для всего текста
  • В 2.5:
    • '...' для данных, u '...' для текста

Я использую Python 2.6.4. Что это значит для меня?

В мире Python в чем разница между данными и текстом?

Ответы

Ответ 1

Вкратце, способ обработки текста и данных в Py3k, возможно, может быть самым "взломанным" изменением в языке. Зная и избегая, когда это возможно, ситуаций, когда какая-то логика Python 2.6 будет работать иначе, чем в 3.x, мы можем облегчить миграцию, когда это произойдет. Однако мы должны ожидать, что некоторые части логики 2.6 могут потребовать особого внимания и модификаций, например, для обработки различных кодировок и т.д.

Идея предложения BDFL на слайде 14, вероятно, должна "использовать" те же типы, которые Py3k поддерживает (и только они), а именно строки unicode для строк (str type) и 8-битовые байтовые последовательности для "данных" (bytes).

Термин "использование" в предыдущем предложении используется довольно слабо, поскольку семантика и связанное с этим хранилище/кодирование для этих типов различаются между версиями 2.6 и 3.x. В Python 2.6 тип байтов и связанный с ним литеральный синтаксис (b'xyz ') просто сопоставляются с типом str. Поэтому

# in Py2.6
>>'mykey' == b'mykey'
True
b'mykey'.__class__
<class 'str'>

# in Py3k
>>>'mykey' == b'mykey'
False
b'mykey'.__class__
<class 'bytes'>  

Чтобы ответить на ваш вопрос [в примечаниях ниже], в 2.6, используете ли вы b'xyz 'или' xyz ', Python понимает это как одно и то же: str. Важно то, что вы понимаете их как [потенциально/в будущем] два разных типа с определенной целью:

  • str для текстовой информации и
  • байты для последовательностей октетов, сохраняющих все имеющиеся данные.

Например, опять же, говоря о вашем примере/вопросе, в Py3k вы сможете иметь словарь с двумя элементами, у которых есть похожие клавиши, один с b'mykey ', а другой с' mykey ', однако до 2.6 это невозможно, так как эти два ключа действительно одинаковы; важно то, что вы знаете подобные вещи и избегаете (или явно отмечаете особым образом в коде) ситуации, когда код 2.6 не работает в 3.x.

В Py3k str представляет собой абстрактную строку юникода, последовательность кодовых точек Юникода (символы) и Python имеет дело с преобразованием этого в/из его кодированной формы независимо от того, какая кодировка может быть (как программист, у вас есть мнение о но в то время, когда вы занимаетесь строковыми операциями, и вам не нужно беспокоиться об этих деталях). Напротив, байты представляют собой последовательность 8-битных "вещей", которые семантика и кодирование полностью оставлены программисту.

Итак, хотя Python 2.6 не видит разницы, явно используя bytes()/b '...' или str()/u '...', вы...

  • ... подготовить себя и свою программу к предстоящим типам и семантике Py3k
  • ... упростить автоматическое преобразование (инструмент 2to3 или другой) исходного кода, в результате чего b в b '...' останется, а u из u '...' будет удален ( поскольку единственный тип строки будет unicode).

Для получения дополнительной информации:
Python 2.6 Что нового (см. литералы Bytes Literations PEP 3112)
Python 3.0 Что нового (см. Text Vs. Data Instead Of Unicode Vs. 8-bit в верхней части)

Ответ 2

Ответ на ваш первый вопрос прост: в Python 2.6 вы можете делать, если привыкли. Но, если хотите, вы можете переключиться на стандарты Py3k, набрав:

from __future__ import unicode_literals

Ваш второй вопрос нуждается в дополнительном разъяснении:

Строки - это данные, которые печатаются как человеческие символы. Не только в Python, но каждый язык (я знаю) имеет свой путь при работе со строками.

Однако общие основания - это кодировки. Кодировки - это способ отображения последовательностей байтов в глифы (т.е. В основном для печатаемых символов).

Python предлагает простой способ преодолеть сложности управления кодировками (когда вы помещаете строковые литералы в свой код).

Посмотрим на очень простой пример:

>>> len("Mañana")
7

Я вижу только 6 символов. Поэтому я ожидаю, что len вернется. 6. Откуда этот дополнительный символ? Ну в UTF-8 символ ñ представлен 2 байтами. До Py3k строковые литералы - это просто последовательности байтов. Итак, Python видит эту строку как байты, и она подсчитывает их все: Ma\xc3\xb1ana.

Однако, если я выполняю следующее:

>>> len(u"Mañana")
6

Итак, Python "точно знает", что 2-байтовые последовательности для "-" следует рассматривать как одну букву.

Это отнюдь не исключительно для Python. Следующий PHP script показывает то же поведение:

[email protected]:~$ php <<EOF
<?php
echo strlen("Mañana")."\n";
?>
EOF
7

Решение PHP более сложное:

[email protected]:~$ php <<EOF
<?php
echo mb_strlen("Mañana", "utf-8")."\n";
?>
EOF
6

Обратите внимание, что я должен заменить mb_strlen на strlen, и мне нужно передать utf-8 (кодировку) в качестве второго аргумента.

Слово предупреждения: пользовательские строки приходят обычно как байты, а не строки unicode. Поэтому вам нужно позаботиться об этом. Подробнее о http://mail.python.org/pipermail/python-list/2008-July/139193.html