Почему Python 3 получился именно таким

May 19, 2017 11:07 · 857 words · 5 minute read перевод python

Оригинал: ‘Why Python 3 exists’ by Brett Cannon

В этом месяце я отвечал на канале Q&A at PuPPY, что в конце концов заставило меня разобраться почему в Python3 появилось разделение по работе со строками и байтами. В итоге я получил благодарности по поводу объяснения, что несколько удивило меня, т.к. я наивно предполагал, что все знают зачем так было сделано. Хотя было бы глупо с моей стороны полагать что каждый - будь то новичок или продвинутый питонист - задавался этим вопросом и пытался найти объяснение. Так что этот пост должен разъяснить почему Python 3 именно такой как есть, и почему мы решили внести несовместимые изменения, разделив строки на unicode/str/bytes, т.к. это одна из самых сложных вещей при портировании кода со второй ветки.

Текстовые и двоичные данные в Python 2 наводят беспорядок

Можете ли быстро ответить что семантически представляют из себя данные символы?

'abcd'

Если вы работаете с Python 3, то скажите, что это строка, содержащая буквы a, b, c, d в данном порядке.

Но на Python 2 это может иметь несколько значений. Например, байты, в которых закодированы числа 97, 98, 99 и 100. В Python 3 мы постарались избежать этой путаницы, оставив только один правильный ответ.

Дзен Python гласит - “должен быть один и желательно только один очевидный способ сделать это”. Имея в языке символы, которые могут представлять как текстовые данные, так и бинарные, мы получаем большую проблему. Например, когда при передаче по сети нам вернётся объект str, то мы никак не сможем определить какого типа эти данные - бинарные или текстовые. Это может порождать трудноуловимые ошибки в коде при неправильной обработке, так как проблематично отыскать в каком именно месте произошёл сбой в конвертации.

Вы можете попробовать утверждать, что эта проблема не существенна, если избегать типа str для текстовых данных и всегда пользоваться исключительно unicode. Хм, вы уверены что все так будут делать? Иногда из-за лени или незнания, а иногда в целях быстродействия разработчики будут игнорировать преобразование в unicode. В любом случае это будет работать лишь до той степени, пока все будут соблюдать соглашение, но никто не идеален, и все мы ошибаемся. Если бы так было на самом деле, то я бы не слышал от каждого, что он нашёл проблемы в коде по кодированию/декодированию данных при миграции на Python 3.

Люди забывают, что избежание ошибок - важная задача языка, и устранение неявности того, что может из себя представлять объект str, весьма этому способствует. “Явное лучше неявного” - в дзен Python прямо сказано, что двусмысленность всегда приводит к ошибкам, и явное разделение данных на бинарные и текстовые очень помогает избежать определённого класса ошибок.

Все остальные поставили на Unicode (и не зря)

Люди частенько забывают насколько стар Python; Гвидо начал разработку в декабре 1989 и выпустил первую версию в феврале 1991. А ведь первый стандарт unicode вышел только в октябре 1991. Большинство языков, созданных после этой даты, предпочли сразу реализовать строки в формате unicode. Python 2 в этом плане не повезло - мало кто использовал unicode при работе со строками, т.к. это было совершенно не обязательно. Но в 2004 году (когда началось планирование Python 3) ситуацию решили исправить.

Поддержка любой письменности очень важна; Python создавался как язык для всех, а не только тех, кто использует латинский алфавит и символы ASCII. Python 3 гарантирует, что код будет доступен для каждого языка, пусть даже разработчик об этом и не заботился специально. Для Python 2 есть ряд проектов, которые отказались от перехода на unicode, что ставит крест на использовании их в мультиязычных проектах.

Мы думаем, что Python только набирает популярность.

В 2004 мы начали работу над PEP 3100 (кстати, изначально он имел номер 3000, но был переименован в 3100, т.к. диапазон 3000 - 3099 зарезервирован для предложений как мы будем вести разработку Python 3). В то время его популярность только набирала обороты, так что если мы хотели исправить ошибки дизайна языка, то нужно было это делать именно тогда. Мы исходили из предположения, что со временем на Python 3 будет написано гораздо больше кода, нежели на Python 2. Во-первых, Python 3 должен пережить Python 2.7; во-вторых, все новые проекты должны создаваться сразу на Python 3. По-этому мы решились на такой шаг и частично поломали обратную совместимость.

Мы никогда не будем более ломать обратную совместимость.

Мы в команде решили, что настолько больших изменений как unicode/str/bytes, больше никогда не будет. Когда мы запустили Python3, мы надеялись, что сообщество закончит активную разработку Python 2, внося туда только исправления ошибок, и переключиться на третью ветку. Этого не произошло, но мы усвоили урок. Кроме того мы не видим фундаментальных недостатков языка, которые могли бы привести к ещё одной потере совместимости. Так что в Python 4 мы не планируем ничего более кардинального, чем удаление поддержки устаревших модулей из стандартной библиотеки.

Заключение

Вот почему Python 3 получился именно таким. Мы поняли, что существует ряд ошибок, на которых программисты постоянно спотыкались из-за перегрузки функции str, так что в Python 3 реализовано полное разделение бинарных и текстовых данных. Это также помогает сохранять все текстовые данные в unicode, что автоматически добавляет поддержку мультиязычности. Мы попытались внести изменения как можно скорее, надеясь, что люди оставят Python 2, но вместо этого мы потратили кучу времени и сил на разработку Python 2/3 - подмножество языка, которое бы одинаково работало бы и для второй, и для третьей ветки.