Подтвердить что ты не робот

Подготовка к конвертации из Python 2.x в 3.x

Как мы все знаем уже (надеюсь), Python 3 медленно начинает заменять Python 2.x. Конечно, это будет много МНОГИЕ лет, прежде чем большая часть существующего кода будет наконец перенесена, но есть вещи, которые мы можем сделать прямо сейчас в нашем коде версии 2.x, чтобы облегчить работу коммутатора.

Очевидно, что мы посмотрим на что нового в 3.x будет полезно, но что мы можем сделать сейчас, чтобы сделать предстоящее преобразование более безболезненное (а также упростить вывод обновлений для параллельных версий, если это необходимо)? Я специально задумываюсь о строках, с которых мы можем начать наши скрипты, что сделает более ранние версии Python более похожими на 3.x, хотя другие привычки также приветствуются.

Самый очевидный код для добавления в верхнюю часть script, о котором я могу думать:

from __future__ import division
from __future__ import print_function
try:
    range = xrange
except NameError:
    pass

Самая очевидная привычка, о которой я могу думать, - это "{0} {1}!".format("Hello", "World") для форматирования строк.

Любые другие строки и хорошие привычки, чтобы войти?

4b9b3361

Ответ 1

Самая большая проблема, которая не может быть адекватно устранена изменениями на микроуровне и 2to3, - это изменение типа строки по умолчанию от байтов до Unicode.

Если вашему коду нужно что-то делать с кодировками и байтовыми вводами-выводами, потребуется скопировать ручное усилие для правильной конвертации, так что вещи, которые должны быть байтами, остаются байтами и соответствующим образом декодируются на нужной стадии, Вы обнаружите, что некоторые строковые методы (в частности, format()) и вызовы библиотеки требуют строк Unicode, поэтому вам могут потребоваться дополнительные циклы декодирования/кодирования, чтобы использовать строки как Unicode, даже если они действительно просто байты.

Этому не помогает тот факт, что некоторые из стандартных модулей библиотеки Python были грубо преобразованы с использованием 2to3 без должного внимания к проблемам с байтами /unicode/encoding, поэтому сами ошибаются в том, какой тип строки подходит. Некоторые из них вырваны, но, по крайней мере, с Python 3.0 до 3.2 вы столкнетесь с запутанным и потенциально ошибочным поведением из пакетов, таких как urllib, email и wsgiref, которые должны знать о байтовых кодировках.

Вы можете улучшить проблему, соблюдая осторожность при написании строкового литерала. Используйте строки u'' для чего-либо, что по сути основано на символьных строках, b'' для чего-либо, что действительно байтов, и '' для типа строки по умолчанию, где это не имеет значения, или вам нужно соответствовать требованиям использования строки вызова библиотеки.

К сожалению, синтаксис b'' был введен только в Python 2.6, поэтому это сокращает пользователей более ранних версий.

ета:

какая разница?

О, мой. Ну...

Байт содержит значение в диапазоне 0-255 и может представлять нагрузку двоичных данных (например, содержимое изображения) или какой-либо текст, и в этом случае должен быть выбран стандарт, как отображать набор символов в эти байты. Большинство этих стандартов кодирования сопоставляют нормальный набор символов ASCII в байтах 0-127 одинаково, поэтому в целом безопасно использовать байтовые строки для обработки текста только ASCII в Python 2.

Если вы хотите использовать любой из символов вне ASCII-набора в байтовой строке, у вас проблемы, потому что каждая кодировка отображает другой набор символов в остальные байтовые значения 128-255, и большинство кодировок могут " t отображает все возможные символы в байты. Это источник всех тех проблем, при которых вы загружаете файл из одного языкового стандарта в приложение Windows в другой языковой стандарт, и все буквы с акцентом или не латинскими буквами меняются на неправильные, что делает нечитаемым беспорядок. (aka 'mojibake.)

Существуют также "многобайтовые кодировки", которые позволяют помещать больше символов в доступное пространство, используя более одного байта для хранения каждого символа. Они были введены для восточноазиатских локаций, так как так много китайских иероглифов. Но есть также UTF-8, более современная многобайтовая кодировка, которая может вместить каждый символ.

Если вы работаете с байтовыми строками в многобайтовой кодировке, и сегодня вы, вероятно, будете, потому что UTF-8 очень широко используется; на самом деле, никакая другая кодировка не должна использоваться в современном приложении - тогда у вас есть еще больше проблем, чем просто отслеживать, с какой кодировкой вы играете. len() будет сообщать вам длину в байтах, а не длину в символах, и если вы начнете индексирование и изменение байтов, вы, скорее всего, сломаете многобайтовую последовательность пополам, создавая недопустимую последовательность и обычно путайте все.

По этой причине Python 1.6 и более поздние версии имеют собственные строки Unicode (пишется u'something'), где каждая единица в строке является символом, а не байтом. Вы можете len() их, нарежьте их, замените их, повторно выведите их, и они всегда будут вести себя надлежащим образом. Для задач обработки текста они, несомненно, лучше, поэтому Python 3 делает их строковым типом по умолчанию (без размещения u до '').

Ловушка заключается в том, что многие существующие интерфейсы, такие как имена файлов в ОС, отличных от Windows, или HTTP или SMTP, в основном основаны на байтах с отдельным способом указания кодировки. Поэтому, когда вы имеете дело с компонентами, которые нуждаются в байтах, вам нужно правильно закодировать строки юникода в байтах, а в Python 3 вам придется делать это явно в некоторых местах, где раньше вам не нужно.

Это внутренняя деталь реализации, в которой строки Unicode берут два байта памяти на единицу внутри. Вы никогда не увидите это хранилище; вы не должны думать об этом с точки зрения байтов. Единицы, над которыми вы работаете, являются концептуально символами, независимо от того, как Python хочет их представлять в памяти.

... в сторону:

Это не совсем так. "Узкие сборки Python, такие как сборка Windows, каждая единица строки Unicode не является технически символом, а модулем UTF-16". Для символов в базовой многоязычной плоскости от 0x0000-0xFFFF вы не заметите какой-либо разницы, но если вы используете символы извне этого 16-битного диапазона, то в "астральных плоскостях" вы обнаружите, что они принимают два единиц вместо одного, и, опять же, вы рискуете разбить персонажа, когда вы нарезаете их.

Это очень плохо, и произошло потому, что Windows (и другие, такие как Java) установили UTF-16 как механизм хранения в памяти до того, как Unicode вырос за пределы 65 000 символов. Тем не менее, использование этих расширенных символов по-прежнему довольно редко, и любой пользователь Windows будет использовать их во многих приложениях, поэтому он, вероятно, не критичен для вас.

В строгих строках Unicode строятся единицы кода реального символа, поэтому даже расширенные символы вне BMP можно обрабатывать последовательно и легко. Цена за это - эффективность: каждый струнный блок занимает 4 байта памяти в памяти.

Ответ 2

Я пытаюсь привыкнуть к таким вещам, как var1//var2, когда я действительно хочу целое деление (а не float). Не большой шаг к Python 3, но по крайней мере мне не придется возвращаться и проверять все мое подразделение:)