Python: данные против текста? - PullRequest
11 голосов
/ 15 ноября 2009

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

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

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

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

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

Ответы [ 2 ]

18 голосов
/ 15 ноября 2009

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

Идея, лежащая в основе предложения BDFL на слайде 14, заключается в том, чтобы, вероятно, начать " с использованием " тех же типов, которые поддерживает Py3k (и только эти), а именно строки Unicode для строк (тип str) и 8- битовые байтовые последовательности для «данных» (bytes тип).

Термин " using " в предыдущем предложении используется довольно свободно, поскольку семантика и связанное хранение / кодирование для этих типов различаются в версиях 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 является абстрактной строкой Unicode, последовательностью кодовых точек (символов) Unicode, и Python имеет дело с преобразованием этого в / из его закодированной формы, какой бы ни была кодировка (как программист, вы действительно говорите о кодирование, но в то время, когда вы имеете дело со строковыми операциями, и вам не нужно беспокоиться об этих деталях). Напротив, байты - это последовательность 8-битных «вещей», семантика и кодирование которых полностью оставлены на усмотрение программиста.

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

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

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

2 голосов
/ 15 ноября 2009

Ответ на ваш первый вопрос прост: в 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 показывает то же поведение:

manu@pavla:~$ php <<EOF
<?php
echo strlen("Mañana")."\n";
?>
EOF
7

Решение PHP получилось более сложным:

manu@pavla:~$ 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...