Fork me on GitHub
2/8/2007

Python 3000 FAQ

Это перевод двух постов Гвидо, где он отвечает на часто задаваемые ему вопросы о Python 3000.

Я хочу изучать Python. Мне следует начинать с Python 2.6 или Python 3.0?

Определенно, стоит начинать с Python 2.x (последняя вышедшая версия - 2.5). Я полагаю что в действительности следует изучать Python 3.0 через пару лет, тем более с точки зрения начинающего различия не такие большие: большинство того, что вы узнаете о 2.x будет таким же и в 3.0.

Если убрали reduce(), почему оставили map() и filter()?

Я убрал reduce() не потому что я ненавижу функциональный подход, а потому что большинство кода с reduce() менее читабельно, чем то же самое, переписанное с циклом for и промежуточной переменной. С другой стороны, map() и filter() часто бывают полезны и когда они используются с уже существующей функцией (т.е. встроенной), то более прозрачны, чем списковые выражения или выражения-генераторы. (Не используйте их вместе с lambda; в этом случае предпочтительней и быстрее списковые выражения.)

В ближайшем будующем многоядерные процессоры будут обычным делом и на ноутбуках. Избавится ли Python 3.0 от GIL (Global Interpreter Lock) для того чтобы использовать преимущества многоядерности?

Нет. Мы не настолько сильно меняем реализацию CPython. Для того, чтобы избавиться от GIL нужно практически полностью переписать интерпретатор, поскольку все внутренние структуры данных (и операции подсчета ссылок) должны быть thread-safe. Как то (в конце 90-х, Грег Стайн) уже была попытка и в результате интерпретатор стал вдвое медленней. Если у вас несколько CPU и вы желаете использовать каждый из них, то создавайте столько процессов, сколько у вас процессоров. (Вы же пишите легко масштабируемые веб-приложения, не так ли? Так если есть возможность запустить несколько копий на нескольких машинах, то задача запуска нескольких копий на одной машине тривиальна.). Если Вам действительно нужна "честная" многопоточность в Python, используйте Jython или IronPython; JVM и CLR имеют поддержку многопроцессорных потоков. Конечно, будьте готовы к взаимным блокировкам, livelock, race condition и всем другим "прелестям", сопровождающим многопоточный код.

Я бы предпочел использовать один и тот же код для 2.x и 3.0; я очень не хочу использовать 2to3 для преобразования кода. Почему бы не обойтись без этого?

Как угодно. 2.6 и 3.0 сильно пересекаются, но есть некоторые вещи, которые не получатся: Вам нельзя использовать ни Unicode-строки (есть только в 2.6), ни байтовые строки (есть только в 3.0). Единственный общий синтаксис для print -- это print(x). Когда вы перехватываете исключение, то у вас нет возможности исследовать ее аргумент, поскольку в 2.6-синтаксисе используется запятая, а в 3.0 -- as. Не получится использовать .iterkeys(), но .keys() можно (хотя работает по-разному в 2.6 и 3.0). И т.д. Ограничение себя только лишь пересечением двух версий неудобно и не всегда возможно. Мы не заявляем обратной совместимости в 3.0, поскольку изначально не было такой цели (мы сохраняем обратную совместимость для всех версий 2.x, так что 3.0 -- это "уборка мусора").

Будет ли в Python 3000 возможность X (еще не рассмотренная)?

Нет. Дедлайн для добавления возможностей (PEP'ов) был 30-го апреля 2007. Я выделю некоторые из них для пояснения, почему различные идеи (большинство из которых не новы) не рассмотрены или отклонены.

Будет ли удалена в Python 3000 неявная конкатенация строк? (т.е., вместо ("a" "b") нужно будет писать ("a" + "b").)

Нет. Это было рассмотрено в PEP 3126 и отклонено.

Будет ли в Python 3000 стандартизирован бинарный API для строк? (в зависимости от условий времени компиляции, юникод-строки могут быть как 2-х байтными, так и 4-х байтными.)

Нет, существуют веские причины для поддержки 2 байтов в одном случае и 4 в другом. Обычно это обходится компилированием исходных текстов используя заголовочные файлы уже установленного Python. Если это не работает и вы обеспокоены этим, я бы посоветовал обратиться в список рассылки python-3000 и объяснить свою позицию.

Почему GIL (Global Interpreter Lock) не рекурсивен?

Несколько причин. Рекурсивные блокировки более дороги, а GIL используется очень часто. Python-пакет thread, написанный на C, не реализует рекурсивные блокировки (это просто добавление на Python, см. RLock в threading.py. ) Ввиду различия API потоков на различных платформах, крайне важно что C-код, завязанный на потоках, был минимален. Но, по видимому, самая серъезная причина такова: GIL часто освобождается около операций ввода-вывода. Освобождение только одного уровня рекурсивной блокировки в данном случае не корректно; кто-нибудь захочет освободить низлежащую нерекурсивную блокировку и восстановить уровень рекурсии после перезахвата. Всё это достаточно закручено. С нерекурсивной блокировкой всё это делается намного проще.

Будет ли в Python 3000 возможность использовать операторы в lambda?

Нет. Синтаксис (отступы внутри выражения) будет сложен как для реализации, так и для чтения. Я рекомендую просто определять локальную (т.е. вложеннную) функцию --- она имеет ту же семантику как lambda, но без синтаксических ограничений. Итак,

foo = lambda: whatever

полностью эквивалентно:

def foo(): return whatever

(кроме разве того, что lambda "не помнит" своего имени).

В Python 3000 нужна хвостовая оптимизация?

Нет. Аргумент таков: то, что это будет "прозрачной" оптимизацией -- не верно, она приводит к изменению стиля, зависимого от хвостовой оптимизации, так что в этом ключе прозрачность теряется. И вообще, почему нужна? :-) Еще, будет сложнее читать трейсбеки. Реальность такова, что Python -- не функциональный язык. Функциональщина работает в большей степени на сторонних эффектах изменяемых объектов, и не будет возможности преобразовывать программу, сохраняя семантику.

Python 3000 будет предоставлять "настоящие" private, protected и public?

Нет. Python будет оставаться языком "открытого кимоно".

Python 3000 будет поддерживать статическую типизацию?

Не так, а то язык станет Java-без-скобок. Тем не менее, вы можете использовать "аннотации аргументов" (PEP 3107, см. также пост Ивана Сагалаева) и написать декоратор или метакласс для типизации аргументов во время выполнения. Я полагаю, что вполне можно написать расширение к pychecker или pylint, которые бы проверяли сигнатуры функций, используя аннотации.

Почему str(c for c in X) не возвращает "склеенную" строку значений c?

Что ж, будем последовательны, str(['a', 'b', 'c']) будет возвращать 'abc'. Это немного не то, что вы хотели бы. Далее, что будет делать str([1, 2, 3])? И это будет большой проблемой, если str() будет вызывать исключение, поскольку это означает невозможность печати аргумента: print вызывает str() для каждого аргумента.

Комментарии

Все статьи