Что нового в Python 2.0¶
- Автор:
А. М. Кюхлинг и Моше Цадка
Вступление¶
16 октября 2000 года был выпущен новый выпуск Python, версия 2.0. В этой статье рассматриваются интересные новые возможности версии 2.0, освещаются некоторые другие полезные изменения и указывается на несколько несовместимых изменений, которые могут потребовать переписывания кода.
Разработка Python никогда полностью не останавливается в перерывах между выпусками, и всегда поступает постоянный поток исправлений ошибок и улучшений. В версии 2.0 появилось множество мелких исправлений, несколько оптимизаций, дополнительные строки документации и улучшенные сообщения об ошибках; перечислить их все было бы невозможно, но они, безусловно, важны. Если вы хотите ознакомиться с полным списком, обратитесь к общедоступным журналам CVS. Этот прогресс достигнут благодаря тому, что пяти разработчикам, работающим в PythonLabs, теперь платят за то, что они целыми днями исправляют ошибки, а также благодаря улучшенной коммуникации в результате перехода на SourceForge.
А как насчет Python 1.6?¶
Версию Python 1.6 можно рассматривать как релиз Python с контрактными обязательствами. После того, как основная команда разработчиков покинула CNRI в мае 2000 года, CNRI запросила создание версии 1.6, содержащей всю работу над Python, которая была выполнена в CNRI. Таким образом, версия Python 1.6 отражает состояние дерева CVS по состоянию на май 2000 года, причем наиболее важной новой функцией является поддержка Unicode. Разумеется, разработка продолжалась и после мая, поэтому дерево версий 1.6 получило несколько исправлений, чтобы обеспечить его прямую совместимость с Python 2.0. Таким образом, версия 1.6 является частью эволюции Python, а не побочной ветвью.
Итак, стоит ли вам проявлять большой интерес к Python 1.6? Вероятно, нет. Релизы 1.6final и 2.0beta1 были выпущены в один и тот же день (5 сентября 2000 года), планировалось завершить разработку Python 2.0 в течение месяца или около того. Если у вас есть приложения, требующие обслуживания, то, по-видимому, нет смысла что-то менять, переходя на версию 1.6, исправляя их, а затем, в течение месяца, снова сталкиваясь с поломками, переходя на версию 2.0; лучше сразу перейти на версию 2.0. Большинство действительно интересных функций, описанных в этом документе, доступны только в 2.0, потому что с мая по сентябрь была проделана большая работа.
Новый процесс разработки¶
Самое важное изменение в Python 2.0, возможно, касается не кода вообще, а того, как разрабатывается Python: в мае 2000 года разработчики Python начали использовать инструменты, доступные от SourceForge, для хранения исходного кода, отслеживания отчетов об ошибках и управления очередью отправки исправлений. Чтобы сообщить об ошибках или отправить исправления для Python 2.0, воспользуйтесь инструментами отслеживания ошибок и управления исправлениями, доступными на странице проекта Python, расположенной по адресу https://sourceforge.net/projects/python/.
Наиболее важным из сервисов, размещенных в настоящее время на SourceForge, является Python CVS tree, хранилище с контролем версий, содержащее исходный код для Python. Ранее доступ на запись к дереву CVS имели примерно 7 человек, и все исправления должны были проверяться и устанавливаться одним из людей из этого короткого списка. Очевидно, что это было не очень масштабируемо. Перенеся дерево CVS в SourceForge, стало возможным предоставить доступ на запись большему числу пользователей; по состоянию на сентябрь 2000 года 27 человек могли вносить изменения, что в четыре раза больше. Это делает возможными крупномасштабные изменения, которые не были бы предприняты, если бы их пришлось отфильтровывать небольшой группе основных разработчиков. Например, однажды Питеру Шнайдер-Кампу взбрело в голову отказаться от совместимости с K&R C и преобразовать исходный код C для Python в ANSI C. Получив одобрение в списке рассылки python-dev, он запустил серию проверок, которые продолжались около недели, к ним присоединились другие разработчики, чтобы помогите, и дело было сделано. Если бы доступ на запись имели только 5 человек, вероятно, эта задача была бы расценена как «приятная, но не стоящая затраченного времени и усилий», и она никогда бы не была выполнена.
Переход к использованию сервисов SourceForge привел к значительному увеличению скорости разработки. Теперь патчи отправляются, комментируются и пересматриваются другими пользователями, а также передаются от одного пользователя к другому, пока патч не будет признан заслуживающим проверки. Ошибки отслеживаются в одном центральном месте и могут быть назначены конкретному специалисту для исправления, а мы можем подсчитать количество открытых ошибок, чтобы оценить прогресс. Это не обошлось без затрат: разработчикам теперь приходится иметь дело с большим количеством электронной почты, подписываться на большее количество списков рассылки, и для новой среды пришлось писать специальные инструменты. Например, SourceForge отправляет сообщения электронной почты с исправлениями и уведомлениями об ошибках по умолчанию, которые совершенно бесполезны, поэтому Ка-Пинг Йи написал HTML-скрейпер, который отправляет больше полезных сообщений.
Простота добавления кода поначалу вызывала некоторые трудности, например, код проверялся до того, как он был готов, или без получения четкого согласия от группы разработчиков. Возникший процесс утверждения в некоторой степени похож на тот, который используется группой Apache. Разработчики могут поставить за патч +1, +0, -0 или -1; +1 и -1 означают принятие или отклонение, в то время как +0 и -0 означают, что разработчик в основном безразличен к изменениям, хотя и с небольшим положительным или отрицательным уклоном. Наиболее существенным отличием от модели Apache является то, что голосование, по сути, носит рекомендательный характер, позволяя Гвидо ван Россуму, который имеет статус пожизненного диктатора-доброжелателя, узнать общее мнение. Он по-прежнему может игнорировать результаты голосования и одобрять или отклонять изменения, даже если сообщество с ним не согласно.
Создание настоящего патча - это последний шаг в добавлении новой функции, и обычно он прост по сравнению с более ранней задачей по созданию хорошего дизайна. Обсуждения новых функций часто перерастают в длинные обсуждения в списках рассылки, из-за чего за ходом обсуждения трудно следить, и никто не может прочитать каждую публикацию в python-dev. Поэтому для написания предложений по улучшению Python (PEP) был разработан относительно формальный процесс, основанный на процессе RFC в Интернете. PEP - это проекты документов, описывающих предлагаемую новую функцию, которые постоянно пересматриваются до тех пор, пока сообщество не достигнет консенсуса, либо приняв, либо отклонив предложение. Цитата из введения к PEP 1, «Цель и рекомендации PEP».:
PEP расшифровывается как Предложение по улучшению Python. PEP - это проектный документ, предоставляющий информацию сообществу Python или описывающий новую функцию для Python. PEP должен содержать краткую техническую спецификацию функции и обоснование ее использования.
Мы планируем, что PEP станут основными механизмами для предложения новых функций, сбора мнений сообщества по той или иной проблеме и документирования дизайнерских решений, принятых в Python. Автор PEP отвечает за достижение консенсуса в сообществе и документирование особых мнений.
Прочтите остальную часть PEP 1, чтобы узнать подробности о процессе редактирования, стиле и формате PEP. Каналы хранятся в дереве Python CVS на SourceForge, хотя они не являются частью дистрибутива Python 2.0 и также доступны в виде HTML по адресу https://peps.python.org/. По состоянию на сентябрь 2000 года существует 25 PEP, в диапазоне от PEP 201, «Пошаговая итерация», до PEP 225, «Поэлементные/объектные операторы».
Юникод¶
Важнейшей новинкой в Python 2.0 является новый базовый тип данных: строки в Unicode. В Unicode для представления символов используются 16-разрядные числа вместо 8-разрядных, используемых в ASCII, что означает, что может поддерживаться 65 536 различных символов.
Окончательный интерфейс для поддержки Unicode был разработан в результате бесчисленных, часто бурных обсуждений в списке рассылки python-dev и в основном реализован Марком-Андре Лембургом на основе реализации типа Unicode string Фредриком Лундомом. Подробное описание интерфейса было написано в виде PEP 100, «Интеграция Python с Unicode». В этой статье мы просто рассмотрим наиболее важные моменты, касающиеся интерфейсов Unicode.
В исходном коде Python строки в Юникоде записываются как u"string"
. Произвольные символы Юникода могут быть записаны с использованием новой управляющей последовательности \uHHHH
, где HHHH - это 4-значное шестнадцатеричное число от 0000 до FFFF. Также может быть использована существующая управляющая последовательность \xHH
, а восьмеричная управляющая последовательность может использоваться для символов длиной до U+01FF, которая представлена как \777
.
Строки Юникода, как и обычные строки, представляют собой неизменяемый тип последовательности. Они могут быть проиндексированы и разделены, но не изменены на месте. В строках Юникода есть метод encode( [encoding] )
, который возвращает 8-разрядную строку в нужной кодировке. Кодировки обозначаются строками, например, 'ascii'
, 'utf-8'
, 'iso-8859-1'
, или как-то еще. Для реализации и регистрации новых кодировок, которые затем доступны во всей программе на Python, определен API-интерфейс кодека. Если кодировка не указана, то по умолчанию обычно используется 7-разрядный формат ASCII, хотя его можно изменить для вашей установки на Python, вызвав функцию sys.setdefaultencoding(encoding)
в настроенной версии site.py
.
Объединение 8-битных строк и строк в Юникоде всегда приводит к преобразованию в Юникод, используя кодировку ASCII по умолчанию; результатом 'a' + u'bc'
будет u'abc'
.
Были добавлены новые встроенные функции, а существующие встроенные модули изменены для поддержки Unicode:
unichr(ch)
возвращает строку в Юникоде длиной в 1 символ, содержащую символ ch.ord(u)
, где u - обычная строка из 1 символа или строка в Юникоде, возвращает номер символа в виде целого числа.unicode(string [, encoding] [, errors] )
создает строку Юникода из 8-разрядной строки.encoding
- это строка, в которой указывается используемая кодировка. Параметрerrors
определяет обработку символов, которые недопустимы для текущей кодировки; передача'strict'
в качестве значения приводит к возникновению исключения при любой ошибке кодирования, в то время как'ignore'
приводит к тому, что ошибки автоматически игнорируются и'replace'
использует U+FFFD, официальный символ замены, на случай возникновения каких-либо проблем.Оператор
exec
и различные встроенные модули, такие какeval()
,getattr()
, иsetattr()
, также будут принимать строки в Юникоде, а также обычные строки. (Возможно, в процессе исправления были упущены некоторые встроенные функции; если вы обнаружите встроенную функцию, которая принимает строки, но вообще не принимает строки в Юникоде, пожалуйста, сообщите об этом как об ошибке.)
Новый модуль, unicodedata
, предоставляет интерфейс для управления свойствами символов Юникода. Например, unicodedata.category(u'A')
возвращает строку из 2 символов «Lu», «L» означает, что это буква, а «u» означает, что она в верхнем регистре. unicodedata.bidirectional(u'\u0660')
возвращает «AN», что означает, что U+0660 - это арабский алфавит. число.
Модуль codecs
содержит функции для поиска существующих кодировок и регистрации новых. Если вы не хотите внедрять новую кодировку, вы чаще всего будете использовать функцию codecs.lookup(encoding)
, которая возвращает кортеж из 4 элементов: (encode_func, decode_func, stream_reader, stream_writer)
.
encode_func - это функция, которая принимает строку в Юникоде и возвращает 2 кортежа
(string, length)
. string - это 8-разрядная строка, содержащая часть (возможно, всю) строки Unicode, преобразованную в заданную кодировку, а length сообщает вам, какая часть строки Unicode была преобразована.decode_func является противоположностью encode_func, принимая 8-разрядную строку и возвращая 2-кортежа
(ustring, length)
, состоящий из результирующей строки Юникода ustring и целого числа length, указывающего, какая часть 8-разрядной строки была использована.stream_reader - это класс, который поддерживает декодирование входных данных из потока. stream_reader(file_obj) возвращает объект, который поддерживает методы
read()
,readline()
, иreadlines()
. Все эти методы будут преобразованы из заданной кодировки и вернут строки в Юникоде.stream_writer, аналогично, является классом, который поддерживает кодирование выходных данных в поток. stream_writer(file_obj) возвращает объект, который поддерживает методы
write()
иwritelines()
. Эти методы ожидают строки в Юникоде, переводя их в заданную кодировку на выходе.
Например, следующий код записывает строку Unicode в файл, кодируя ее как UTF-8:
import codecs
unistr = u'\u0660\u2000ab ...'
(UTF8_encode, UTF8_decode,
UTF8_streamreader, UTF8_streamwriter) = codecs.lookup('UTF-8')
output = UTF8_streamwriter( open( '/tmp/output', 'wb') )
output.write( unistr )
output.close()
Затем следующий код будет считывать вводимые данные в формате UTF-8 из файла:
input = UTF8_streamreader( open( '/tmp/output', 'rb') )
print repr(input.read())
input.close()
Регулярные выражения, поддерживающие Юникод, доступны через модуль re
, который имеет новую базовую реализацию под названием SRE, написанную Фредриком Лундом (Fredrik Lundh) из Secret Labs AB.
Был добавлен параметр командной строки -U
, который заставляет компилятор Python интерпретировать все строковые литералы как строковые литералы Unicode. Это предназначено для использования при тестировании и доработке вашего кода на Python, поскольку в некоторых будущих версиях Python может быть отменена поддержка 8-битных строк и будут доступны только строки в кодировке Unicode.
Перечислите понятия¶
Списки - это тип данных «рабочей лошадки» в Python, и многие программы в какой-то момент манипулируют списком. Две распространенные операции со списками - это перебор их в цикле и либо выбор элементов, соответствующих определенному критерию, либо применение некоторой функции к каждому элементу. Например, имея список строк, вы можете захотеть удалить все строки, содержащие заданную подстроку, или убрать завершающие пробелы из каждой строки.
Для этой цели можно использовать существующие функции map()
и filter()
, но для них требуется функция в качестве одного из аргументов. Это нормально, если есть существующая встроенная функция, которую можно передать напрямую, но если ее нет, вам нужно создать небольшую функцию для выполнения требуемой работы, а правила определения области видимости Python делают результат уродливым, если маленькой функции требуется дополнительная информация. Возьмем первый пример из предыдущего абзаца, в котором мы находим все строки в списке, содержащие заданную подстроку. Для этого можно написать следующее:
# Given the list L, make a list of all strings
# containing the substring S.
sublist = filter( lambda s, substring=S:
string.find(s, substring) != -1,
L)
Из-за правил определения области видимости в Python используется аргумент по умолчанию, чтобы анонимная функция, созданная с помощью выражения lambda
, знала, какую подстроку ищут. Использование списка упрощает эту задачу:
sublist = [ s for s in L if string.find(s, S) != -1 ]
Понимания списка имеют вид:
[ expression for expr in sequence1
for expr2 in sequence2 ...
for exprN in sequenceN
if condition ]
Предложения for
…in
содержат последовательности, по которым необходимо выполнить итерацию. Последовательности не обязательно должны быть одинаковой длины, поскольку они повторяются не параллельно, а слева направо; это объясняется более четко в следующих параграфах. Элементами сгенерированного списка будут последовательные значения выражения. Последнее предложение if
необязательно; если оно присутствует, выражение вычисляется и добавляется к результату только в том случае, если условие истинно.
Чтобы сделать семантику предельно ясной, понимание списка эквивалентно следующему коду на Python:
for expr1 in sequence1:
for expr2 in sequence2:
...
for exprN in sequenceN:
if (condition):
# Append the value of
# the expression to the
# resulting list.
Это означает, что при наличии нескольких предложений for
…in
результирующий список будет равен произведению длин всех последовательностей. Если у вас есть два списка длиной 3, выходной список будет состоять из 9 элементов:
seq1 = 'abc'
seq2 = (1,2,3)
>>> [ (x,y) for x in seq1 for y in seq2]
[('a', 1), ('a', 2), ('a', 3), ('b', 1), ('b', 2), ('b', 3), ('c', 1),
('c', 2), ('c', 3)]
Чтобы избежать двусмысленности в грамматике Python, если expression создает кортеж, он должен быть заключен в круглые скобки. Первое значение в приведенном ниже списке является синтаксической ошибкой, в то время как второе - правильным:
# Syntax error
[ x,y for x in seq1 for y in seq2]
# Correct
[ (x,y) for x in seq1 for y in seq2]
Идея создания списков изначально была заимствована из функционального языка программирования Haskell (https://www.haskell.org). Грег Юинг наиболее эффективно аргументировал необходимость добавления их в Python и написал первоначальный патч для понимания списка, который затем бесконечно долго обсуждался в списке рассылки python-dev и постоянно обновлялся Скипом Монтанаро.
Расширенное назначение¶
В Python 2.0 добавлены расширенные операторы присваивания, еще одна давно запрашиваемая функция. Расширенные операторы присваивания включают в себя +=
, -=
, *=
, и так далее. Например, оператор a += 2
увеличивает значение переменной a
на 2, что эквивалентно более длинному a = a + 2
.
Полный список поддерживаемых операторов присваивания приведен ниже +=
, -=
, *=
, /=
, %=
, **=
, &=
, |=
, ^=
, >>=
, и <<=
. Классы Python могут переопределять расширенные операторы присваивания, определяя методы с именами __iadd__()
, __isub__()
, и т.д. Например, следующий класс Number
хранит число и поддерживает использование += для создания нового экземпляра с увеличенным значением.
class Number:
def __init__(self, value):
self.value = value
def __iadd__(self, increment):
return Number( self.value + increment)
n = Number(5)
n += 3
print n.value
Специальный метод __iadd__()
вызывается со значением increment и должен возвращать новый экземпляр с соответствующим образом измененным значением; это возвращаемое значение привязывается к новому значению переменной в левой части.
Операторы расширенного присваивания были впервые представлены в языке программирования C, и большинство языков, производных от C, таких как awk, C++, Java, Perl и PHP, также поддерживают их. Исправление расширенного присваивания было реализовано Томасом Ваутерсом.
Строковые методы¶
До сих пор функциональность манипулирования строками находилась в модуле string
, который обычно был интерфейсом для модуля strop
, написанного на C. Добавление Unicode создало трудности для модуля strop
, поскольку все функции должны были быть переписаны, чтобы принимать либо 8-разрядные строки, либо строки в Юникоде. Для таких функций, как string.replace()
, которые принимают 3 строковых аргумента, это означает восемь возможных перестановок и, соответственно, сложный код.
Вместо этого Python 2.0 переносит проблему на тип string, делая функциональность манипулирования строками доступной с помощью методов как для 8-битных строк, так и для строк в Юникоде.
>>> 'andrew'.capitalize()
'Andrew'
>>> 'hostname'.replace('os', 'linux')
'hlinuxtname'
>>> 'moshe'.find('sh')
2
Единственное, что не изменилось, несмотря на примечательную первоапрельскую шутку, - это то, что строки Python неизменяемы. Таким образом, методы string возвращают новые строки и не изменяют строку, с которой они работают.
Старый модуль string
все еще используется для обеспечения обратной совместимости, но в основном он служит интерфейсом для новых методов string.
Два метода, которые не имели аналогов в версиях до версии 2.0, хотя и существовали в JPython довольно долгое время, - это startswith()
и endswith()
. s.startswith(t)
эквивалентно s[:len(t)] == t
, в то время как s.endswith(t)
эквивалентно s[-len(t):] == t
.
Еще один метод, заслуживающий особого упоминания, - это join()
. Метод join()
string принимает один параметр, последовательность строк, и эквивалентен функции string.join()
из старого модуля string
, с измененными аргументами. Другими словами, s.join(seq)
эквивалентно старому string.join(seq, s)
.
Сборка мусора из циклов¶
Реализация Python на языке Си использует подсчет ссылок для реализации сборки мусора. Каждый объект Python ведет подсчет количества ссылок, указывающих на него, и корректирует это количество по мере создания или уничтожения ссылок. Как только количество ссылок достигает нуля, объект больше недоступен, поскольку для доступа к нему вам нужна ссылка на объект, а если количество равно нулю, ссылок больше не существует.
Подсчет ссылок обладает некоторыми приятными свойствами: его легко понять и реализовать, а результирующая реализация является переносимой, довольно быстрой и хорошо взаимодействует с другими библиотеками, которые реализуют свои собственные схемы обработки памяти. Основная проблема с подсчетом ссылок заключается в том, что он иногда не осознает, что объекты больше недоступны, что приводит к утечке памяти. Это происходит, когда есть циклы ссылок.
Рассмотрим простейший из возможных циклов - экземпляр класса, который имеет ссылку на сам себя:
instance = SomeClass()
instance.myself = instance
После выполнения двух приведенных выше строк кода количество ссылок instance
равно 2; одна ссылка относится к переменной с именем 'instance'
, а другая - к атрибуту экземпляра myself
.
Если следующая строка кода будет del instance
, что произойдет? Количество ссылок в instance
уменьшено на 1, поэтому количество ссылок равно 1; ссылка в атрибуте myself
по-прежнему существует. Однако этот экземпляр больше недоступен через код на Python и может быть удален. В цикле могут участвовать несколько объектов, если у них есть ссылки друг на друга, что приводит к утечке всех объектов.
Python 2.0 устраняет эту проблему, периодически запуская алгоритм обнаружения циклов, который ищет недоступные циклы и удаляет задействованные объекты. Новый модуль gc
предоставляет функции для выполнения сборки мусора, получения статистики отладки и настройки параметров сборщика.
Запуск алгоритма обнаружения циклов занимает некоторое время и, следовательно, приведет к некоторым дополнительным затратам. Мы надеемся, что после того, как мы приобретем опыт работы с коллекцией циклов, используя версию 2.0, Python 2.1 сможет свести к минимуму затраты при тщательной настройке. Пока не очевидно, насколько сильно теряется производительность, поскольку провести сравнительный анализ сложно и в решающей степени зависит от того, как часто программа создает и уничтожает объекты. Обнаружение циклов можно отключить при компиляции Python, если вы не можете позволить себе даже незначительное снижение скорости или подозреваете, что коллекция циклов содержит ошибки, указав переключатель --without-cycle-gc
при запуске скрипта configure.
Несколько человек занялись этой проблемой и внесли свой вклад в ее решение. Тоби Келси (Toby Kelsey) написал первую версию подхода к обнаружению циклов. Текущий алгоритм был предложен Эриком Тидеманном во время визита в CNRI, а Гвидо ван Россум и Нил Шеменауэр написали две разные реализации, которые позже были интегрированы Нилом. Многие другие люди предлагали свои предложения по ходу дела; архивы списка рассылки python-dev за март 2000 года содержат большую часть соответствующих обсуждений, особенно в темах, озаглавленных «Коллекция справочных циклов для Python» и «Повторная доработка».
Другие основные изменения¶
В синтаксис и встроенные функции Python были внесены различные незначительные изменения. Ни одно из изменений не является слишком масштабным, но они удобны.
Незначительные языковые изменения¶
Новый синтаксис делает более удобным вызов данной функции с помощью набора аргументов и/или словаря аргументов по ключевым словам. В Python 1.5 и более ранних версиях вы могли бы использовать встроенную функцию apply()
: apply(f, args, kw)
вызывает функцию f()
с аргументом tuple args и ключевыми аргументами в словаре kw. apply()
- это то же самое, что и в версии 2.0, но благодаря патчу от Грега Юинга, f(*args, **kw)
- это более короткий и понятный способ добиться того же эффекта. Этот синтаксис симметричен синтаксису определения функций:
def f(*args, **kw):
# args is a tuple of positional args,
# kw is a dictionary of keyword args
...
Оператор print
теперь может направлять свои выходные данные на объект, подобный файлу, если после print
использовать >> file
, аналогично оператору перенаправления в оболочках Unix. Ранее вам приходилось либо использовать метод write()
файлоподобного объекта, которому не хватает удобства и простоты print
, либо вы могли присвоить новое значение sys.stdout
, а затем восстановить старое значение. Для отправки выходных данных в стандартную ошибку гораздо проще написать следующее:
print >> sys.stderr, "Warning: action field not supplied"
Модули теперь можно переименовывать при импорте, используя синтаксис import module as name
или from module import name as othername
. Патч был представлен Томасом Ваутерсом.
Новый стиль форматирования доступен при использовании оператора %
; „%r“ вставит repr()
в свой аргумент. Это также было добавлено из соображений симметрии, на этот раз для симметрии с существующим стилем формата „%s“, который вставляет str()
в свой аргумент. Например, '%r %s' % ('abc', 'abc')
возвращает строку, содержащую 'abc' abc
.
Ранее не было способа реализовать класс, который переопределял бы встроенный в Python оператор in
и реализовывал пользовательскую версию. obj in seq
возвращает значение true, если obj присутствует в последовательности seq; Python вычисляет это, просто перебирая каждый индекс последовательности, пока не будет найден либо obj, либо IndexError
. Моше Цадка внес свой вклад в исправление, которое добавляет волшебный метод __contains__()
для обеспечения пользовательской реализации для in
. Кроме того, новые встроенные объекты, написанные на C, могут определять, что для них означает in
, с помощью нового слота в протоколе последовательности.
В более ранних версиях Python использовался рекурсивный алгоритм удаления объектов. Глубоко вложенные структуры данных могли привести к переполнению стека C и аварийному завершению работы интерпретатора; Кристиан Тисмер переписал логику удаления, чтобы устранить эту проблему. В связи с этим отметим, что сравнение рекурсивных объектов бесконечно повторяется и приводит к сбою; Джереми Хилтон переписал код, чтобы больше не вызывать сбои, и вместо этого выдал полезный результат. Например, после этого кода:
a = []
b = []
a.append(a)
b.append(b)
Сравнение a==b
возвращает значение true, поскольку две рекурсивные структуры данных изоморфны. Смотрите тему «trashcan и PR#7» в архивах списка рассылки python-dev за апрель 2000 года, в которой обсуждается эта реализация, и некоторые полезные ссылки на нее. Обратите внимание, что при сравнении теперь также могут возникать исключения. В более ранних версиях Python операция сравнения, такая как cmp(a,b)
, всегда выдавала ответ, даже если пользовательский метод __cmp__()
обнаруживал ошибку, поскольку результирующее исключение просто автоматически проглатывалось.
Была проделана работа по переносу Python на 64-разрядную Windows на процессоре Itanium, в основном Трентом Миком из ActiveState. (Странно, но sys.platform
по-прежнему 'win32'
в Win64, потому что, похоже, для простоты переноса MS Visual C++ обрабатывает код как 32-разрядный на Itanium.) PythonWin также поддерживает Windows CE; дополнительную информацию смотрите на странице Python CE по адресу https://pythonce.sourceforge.net/.
Еще одна новая платформа - Darwin/macOS X; начальная поддержка для нее есть в Python 2.0. Динамическая загрузка работает, если вы укажете «configure -with-dyld -with-suffix=.x». Обратитесь к README в исходном коде дистрибутива Python для получения дополнительных инструкций.
Была предпринята попытка устранить одну из проблем Python - часто приводящее в замешательство исключение NameError
, когда код ссылается на локальную переменную до того, как переменной было присвоено значение. Например, следующий код вызывает исключение для инструкции print
как в версиях 1.5.2, так и в версиях 2.0; в версии 1.5.2 возникает исключение NameError
, в то время как в версии 2.0 возникает новое исключение UnboundLocalError
. UnboundLocalError
является подклассом NameError
, поэтому любой существующий код, который ожидает вызова NameError
, все равно должен работать.
def f():
print "i=",i
i = i + 1
f()
Были введены два новых исключения, TabError
и IndentationError
. Оба они являются подклассами SyntaxError
и вызываются, когда обнаруживается, что в коде Python неправильный отступ.
Изменения во встроенных функциях¶
Добавлена новая встроенная функция zip(seq1, seq2, ...)
. zip()
возвращает список кортежей, в котором каждый кортеж содержит i-й элемент из каждой последовательности аргументов. Разница между zip()
и map(None, seq1, seq2)
заключается в том, что map()
заменяет последовательности None
, если последовательности не все одинаковой длины, в то время как zip()
усекает возвращаемые значения. перечислите до длины самой короткой последовательности аргументов.
Функции int()
и long()
теперь принимают необязательный параметр «base», если первый аргумент является строкой. int('123', 10)
возвращает значение 123, в то время как int('123', 16)
возвращает значение 291. int(123, 16)
вызывает TypeError
исключение с сообщением «не удается преобразовать нестроковое значение с явной базой».
В модуль sys
добавлена новая переменная, содержащая более подробную информацию о версии. sys.version_info
- это кортеж (major, minor, micro, level, serial)
Например, в гипотетическом 2.0.1beta1, sys.version_info
будет (2, 0, 1, 'beta', 1)
. level - это строка, такая как "alpha"
, "beta"
, или "final"
для окончательного выпуска.
В словарях есть странный новый метод, setdefault(key, default)
, который ведет себя аналогично существующему методу get()
. Однако, если ключ отсутствует, setdefault()
возвращает значение default, как это сделал бы get()
, а также вставляет его в словарь в качестве значения для key. Таким образом, следующие строки кода:
if dict.has_key( key ): return dict[key]
else:
dict[key] = []
return dict[key]
может быть сведено к одному оператору return dict.setdefault(key, [])
.
Интерпретатор устанавливает максимальную глубину рекурсии, чтобы перехватить неконтролируемую рекурсию перед заполнением стека C и вызовом дампа ядра или GPF. Ранее это ограничение было зафиксировано при компиляции Python, но в версии 2.0 максимальная глубина рекурсии может быть считана и изменена с помощью sys.getrecursionlimit()
и sys.setrecursionlimit()
. Значение по умолчанию равно 1000, и приблизительное максимальное значение для данной платформы можно найти, запустив новый скрипт Misc/find_recursionlimit.py
.
Перенос на версию 2.0¶
Новые версии Python прилагают все усилия, чтобы быть совместимыми с предыдущими версиями, и результаты были довольно хорошими. Однако некоторые изменения считаются достаточно полезными, как правило, потому, что они исправляют первоначальные дизайнерские решения, которые оказались ошибочными, что не всегда позволяет избежать нарушения обратной совместимости. В этом разделе перечислены изменения в Python 2.0, которые могут привести к поломке старого кода Python.
Изменение, которое, вероятно, приведет к нарушению большей части кода, - это ужесточение аргументов, принимаемых некоторыми методами. Некоторые методы принимают несколько аргументов и обрабатывают их как кортеж, особенно различные методы списка, такие как append()
и insert()
. В более ранних версиях Python, если L
является списком, L.append( 1,2 )
добавляет кортеж (1,2)
к списку. В Python 2.0 это приводит к возникновению исключения TypeError
с сообщением: «Для добавления требуется ровно 1 аргумент; задано 2». Исправление заключается в том, чтобы просто добавить дополнительный набор круглых скобок для передачи обоих значений в виде кортежа: L.append( (1,2) )
.
Более ранние версии этих методов были более щадящими, поскольку они использовали старую функцию в интерфейсе Python C для анализа своих аргументов; в версии 2.0 они модернизированы для использования:c:func:PyArg_ParseTuple, текущей функции анализа аргументов, которая предоставляет более полезные сообщения об ошибках и рассматривает вызовы с несколькими аргументами как ошибки. Если вам абсолютно необходимо использовать версию 2.0, но вы не можете исправить свой код, вы можете отредактировать Objects/listobject.c
и определить символ препроцессора NO_STRICT_LIST_APPEND
, чтобы сохранить старое поведение; это не рекомендуется.
Некоторые функции в модуле socket
по-прежнему работают таким образом. Например, socket.connect( ('hostname', 25) )
является правильной формой, передающей кортеж, представляющий IP-адрес, но socket.connect('hostname', 25)
также работает. socket.connect_ex
и socket.bind
также просты в использовании. 2.0alpha1 упростил эти функции, но поскольку в документации фактически использовалась ошибочная форма с несколькими аргументами, многие люди написали код, который сломался бы при более строгой проверке. GvR отменил изменения, несмотря на реакцию общественности, поэтому для модуля socket
документация была исправлена, а форма с несколькими аргументами просто помечена как устаревшая; она будет исправлена в будущей версии Python.
Символ \x
в строковых литералах теперь принимает ровно 2 шестнадцатеричные цифры. Раньше он использовал бы все шестнадцатеричные цифры, следующие за «x», и брал бы младшие 8 бит результата, поэтому \x123456
было эквивалентно \x56
.
Исключения AttributeError
и NameError
содержат более понятное сообщение об ошибке, текст которого будет примерно таким: 'Spam' instance has no attribute 'eggs'
или name 'eggs' is not defined
. Ранее сообщением об ошибке было просто отсутствие имени атрибута eggs
, и код, написанный для использования этого факта, будет работать неправильно в версии 2.0.
Была проделана некоторая работа, чтобы сделать целые числа и длинные целые числа более взаимозаменяемыми. В версии 1.5.2 для Solaris была добавлена поддержка больших файлов, позволяющая читать файлы размером более 2 гигабайт; это привело к тому, что метод tell()
файловых объектов возвращал длинное целое число вместо обычного целого числа. Некоторый код мог бы вычесть два смещения файла и попытаться использовать результат для умножения последовательности или разбиения строки на фрагменты, но это вызвало бы ошибку TypeError
. В версии 2.0 длинные целые числа можно использовать для умножения или разбиения последовательности на части, и она будет вести себя так, как вы интуитивно ожидаете; 3L * 'abc'
выдает „abcabcabc“, а (0,1,2,3)[2L:4L]
выдает (2,3). Длинные целые числа также могут использоваться в различных контекстах, где ранее принимались только целые числа, например, в методе seek()
для файловых объектов и в форматах, поддерживаемых оператором %
(%d
, %i
, %x
, и т.д.). Например, "%d" % 2L**64
приведет к появлению строки 18446744073709551616
.
Самое тонкое изменение длинного целого числа из всех заключается в том, что в str()
длинного целого числа больше нет завершающего символа «L», хотя repr()
по-прежнему содержит его. Буква «L» раздражала многих людей, которые хотели печатать длинные целые числа, которые выглядели бы точно так же, как обычные целые числа, поскольку им приходилось из кожи вон лезть, чтобы сократить этот символ. В версии 2.0 это больше не проблема, но код, который выполняет str(longval)[:-1]
и предполагает наличие буквы «L», теперь потеряет последнюю цифру.
При использовании repr()
в качестве числа с плавающей запятой теперь используется другая точность форматирования, чем str()
. repr()
используется %.17g
строка формата для sprintf()
, в то время как str()
использует %.12g
, как и раньше. В результате для некоторых чисел repr()
иногда может отображаться больше знаков после запятой, чем str()
. Например, число 8.1 не может быть точно представлено в двоичном формате, поэтому repr(8.1)
равно '8.0999999999999996'
, в то время как str(8.1) равно '8.1'
.
Параметр командной строки -X
, который превращал все стандартные исключения в строки вместо классов, был удален; стандартными исключениями теперь всегда будут классы. Модуль exceptions
, содержащий стандартные исключения, был переведен из Python во встроенный модуль C, написанный Барри Уорсо и Фредриком Лундом.
Расширение/внедрение изменений¶
Некоторые изменения скрыты и будут заметны только тем, кто пишет модули расширения C или внедряет интерпретатор Python в более крупное приложение. Если вы не имеете дела с C API Python, вы можете спокойно пропустить этот раздел.
Номер версии Python C API был увеличен, поэтому расширения C, скомпилированные для версии 1.5.2, должны быть перекомпилированы для работы с версией 2.0. В Windows для Python 2.0 невозможно импортировать стороннее расширение, созданное для Python 1.5.x, из-за того, как работают библиотеки DLL для Windows, поэтому Python вызовет возникнет исключение, и импорт завершится неудачей.
Пользователи модуля ExtensionClass Джима Фултона будут рады узнать, что были добавлены перехватчики, так что классы расширений теперь поддерживаются isinstance()
и issubclass()
. Это означает, что вам больше не нужно запоминать написание кода, такого как if type(obj) == myExtensionClass
, но вы можете использовать более естественный if isinstance(obj, myExtensionClass)
.
Файл Python/importdl.c
, который представлял собой набор #ifdefs для поддержки динамической загрузки на многих различных платформах, был очищен и реорганизован Грегом Стайном. importdl.c
теперь довольно маленький, и код, относящийся к конкретной платформе, был перенесен в кучу файлов Python/dynload_*.c
. Еще одна очистка: в каталоге Include/ также было несколько файлов my*.h
, которые содержали различные хаки для переносимости; они были объединены в один файл, Include/pyport.h
.
Владимир Марангозов завершилась долгожданная реструктуризация malloc, которая упростила использование интерпретатором Python пользовательского распределителя вместо стандартного для C:c:func:malloc. Документацию можно найти в комментариях в разделах Include/pymem.h
и Include/objimpl.h
. Подробная информация о длительных обсуждениях, в ходе которых разрабатывался интерфейс, содержится в веб-архивах со списками «исправлений» и «python-dev» по адресу python.org.
Последние версии среды разработки с графическим интерфейсом для macOS поддерживают потоки POSIX. Таким образом, поддержка потоков POSIX в Python теперь работает и на Macintosh. Также была добавлена поддержка потоков с использованием библиотеки пользовательского пространства GNU pth
.
Поддержка многопоточности в Windows также была улучшена. Windows поддерживает блокировки потоков, которые используют объекты ядра только в случае конфликтов; в обычном случае, когда конфликтов нет, используются более простые функции, которые на порядок быстрее. Многопоточная версия Python 1.5.2 для NT работает в два раза медленнее, чем непоточная версия; с изменениями версии 2.0 разница составляет всего 10%. Эти улучшения были внесены Яковом Марковичем.
Исходный код Python 2.0 теперь использует только прототипы ANSI C, поэтому для компиляции Python теперь требуется компилятор ANSI C, и его больше нельзя выполнять с помощью компилятора, поддерживающего только K&R C.
Ранее виртуальная машина Python использовала 16-разрядные числа в своем байт-коде, что ограничивало размер исходных файлов. В частности, это повлияло на максимальный размер списков букв и словарей в исходном коде Python; иногда люди, создающие код на Python, сталкивались с этим ограничением. Исправление Чарльза Г. Уолдмана повышает ограничение с 2**16
до 2**32
.
Были добавлены три новые удобные функции, предназначенные для добавления констант в словарь модуля во время инициализации модуля: PyModule_AddObject()
, PyModule_AddIntConstant()
и PyModule_AddStringConstant()
. Каждая из этих функций принимает объект module, строку C, заканчивающуюся нулем, содержащую имя, которое нужно добавить, и третий аргумент, указывающий значение, которое нужно присвоить имени. Этот третий аргумент, соответственно, является объектом Python, длиной C или строкой C.
Был добавлен API-оболочка для обработчиков сигналов в стиле Unix. PyOS_getsig()
получает обработчик сигнала, а PyOS_setsig()
устанавливает новый обработчик.
Дистрибутивы: Упрощение установки модулей¶
До Python 2.0 установка модулей была утомительным делом - не было способа автоматически определить, где установлен Python или какие параметры компилятора использовать для модулей расширения. Авторам программного обеспечения пришлось пройти через сложный ритуал редактирования Make-файлов и файлов конфигурации, которые действительно работают только в Unix и не поддерживают Windows и macOS. Пользователи Python сталкивались с совершенно разными инструкциями по установке, которые варьировались в зависимости от различных пакетов расширений, что делало администрирование установки Python чем-то вроде рутинной работы.
Команда SIG для дистрибутивных утилит, возглавляемая Грегом Уордом, создала Distutils, систему, значительно упрощающую установку пакетов. Они образуют пакет distutils
, новую часть стандартной библиотеки Python. В лучшем случае установка модуля Python из исходного кода потребует тех же действий: сначала вы просто распакуете tarball или zip-архив, а затем запустите «python setup.py install
». Платформа будет определена автоматически, компилятор распознан, модули расширения C будут скомпилированы, а дистрибутив установлен в соответствующий каталог. Необязательные аргументы командной строки обеспечивают больший контроль над процессом установки, пакет distutils предлагает множество возможностей для переопределения настроек по умолчанию - отделение сборки от установки, создание или установка в каталоги, отличные от каталогов по умолчанию, и многое другое.
Чтобы использовать дистрибутивы, вам нужно написать скрипт setup.py
. В простом случае, когда программа содержит только py-файлы, минимальное значение setup.py
может составлять всего несколько строк:
from distutils.core import setup
setup (name = "foo", version = "1.0",
py_modules = ["module1", "module2"])
Файл setup.py
не намного сложнее, если программное обеспечение состоит из нескольких пакетов:
from distutils.core import setup
setup (name = "foo", version = "1.0",
packages = ["package", "package.subpackage"])
Расширение C может быть самым сложным случаем; вот пример, взятый из пакета PyXML:
from distutils.core import setup, Extension
expat_extension = Extension('xml.parsers.pyexpat',
define_macros = [('XML_NS', None)],
include_dirs = [ 'extensions/expat/xmltok',
'extensions/expat/xmlparse' ],
sources = [ 'extensions/pyexpat.c',
'extensions/expat/xmltok/xmltok.c',
'extensions/expat/xmltok/xmlrole.c', ]
)
setup (name = "PyXML", version = "0.5.4",
ext_modules =[ expat_extension ] )
Distutils также может позаботиться о создании дистрибутивов с исходным кодом и двоичных файлов. Команда «sdist», выполняемая с помощью «python setup.py sdist
“,, создает дистрибутив с исходным кодом, такой как foo-1.0.tar.gz
. Добавлять новые команды несложно, команды «bdist_rpm» и «bdist_wininst» уже использовались для создания дистрибутива RPM и установщика Windows для программного обеспечения соответственно. Команды для создания других форматов распространения, таких как пакеты Debian и файлы Solaris .pkg
, находятся на различных стадиях разработки.
Все это описано в новом руководстве «Распространение модулей Python», которое дополняет базовый набор документации по Python.
XML-модули¶
В Python 1.5.2 был включен простой синтаксический анализатор XML в виде модуля xmllib
, предоставленный Сьердом Маллендером. С момента выхода версии 1.5.2 два различных интерфейса для обработки XML стали общепринятыми: SAX2 (версия 2 Simple API для XML) предоставляет управляемый событиями интерфейс, имеющий некоторое сходство с xmllib
, а DOM (объектная модель документа) предоставляет древовидный интерфейс, преобразующий XML-документ преобразуется в дерево узлов, по которым можно перемещаться и изменять. Python 2.0 включает в себя интерфейс SAX2 и упрощенный интерфейс DOM как часть пакета xml
. Здесь мы дадим краткий обзор этих новых интерфейсов; для получения более подробной информации обратитесь к документации по Python или исходному коду. XML-SIG на Python также работает над улучшенной документацией.
Поддержка SAX2¶
SAX определяет управляемый событиями интерфейс для синтаксического анализа XML. Чтобы использовать SAX, необходимо написать класс обработчика SAX. Классы обработчиков наследуются от различных классов, предоставляемых SAX, и переопределяют различные методы, которые затем будут вызываться анализатором XML. Например, методы startElement()
и endElement()
вызываются для каждого начального и конечного тега, с которым сталкивается синтаксический анализатор, метод characters()
вызывается для каждого фрагмента символьных данных и так далее.
Преимущество подхода, основанного на событиях, заключается в том, что весь документ не обязательно должен находиться в памяти в любой момент времени, что важно, если вы обрабатываете действительно большие документы. Однако написание класса обработчика SAX может оказаться очень сложным, если вы пытаетесь каким-либо сложным образом изменить структуру документа.
Например, этот небольшой пример программы определяет обработчик, который печатает сообщение для каждого начального и конечного тега, а затем анализирует файл hamlet.xml
, используя его:
from xml import sax
class SimpleHandler(sax.ContentHandler):
def startElement(self, name, attrs):
print 'Start of element:', name, attrs.keys()
def endElement(self, name):
print 'End of element:', name
# Create a parser object
parser = sax.make_parser()
# Tell it what handler to use
handler = SimpleHandler()
parser.setContentHandler( handler )
# Parse a file!
parser.parse( 'hamlet.xml' )
Для получения дополнительной информации обратитесь к документации по Python или руководству по XML по адресу https://pyxml.sourceforge.net/topics/howto/xml-howto.html.
Поддержка DOM¶
Объектная модель документа представляет собой древовидное представление XML-документа. Экземпляр верхнего уровня Document
является корнем дерева и имеет единственный дочерний элемент, который является экземпляром верхнего уровня Element
. У этого Element
есть дочерние узлы, представляющие символьные данные, и любые подэлементы, которые могут иметь собственные дочерние узлы и так далее. Используя DOM, вы можете перемещаться по результирующему дереву любым удобным вам способом, получать доступ к значениям элементов и атрибутов, вставлять и удалять узлы и преобразовывать дерево обратно в XML.
DOM полезен для изменения XML-документов, поскольку вы можете создать дерево DOM, изменить его, добавив новые узлы или переставив поддеревья, а затем создать новый XML-документ в качестве выходных данных. Вы также можете создать дерево DOM вручную и преобразовать его в XML, что может быть более гибким способом получения выходных данных XML, чем простая запись <tag1>
…</tag1>
в файл.
Реализация DOM, входящая в состав Python, находится в модуле xml.dom.minidom
. Это упрощенная реализация DOM 1-го уровня с поддержкой пространств имен XML. Для создания дерева DOM предусмотрены удобные функции parse()
и parseString()
:
from xml.dom import minidom
doc = minidom.parse('hamlet.xml')
doc
- это экземпляр Document
. Document
, как и все другие классы DOM, такие как Element
и Text
, является подклассом базового класса Node
. Таким образом, все узлы в дереве DOM поддерживают определенные общие методы, такие как toxml()
, который возвращает строку, содержащую XML-представление узла и его дочерних элементов. У каждого класса также есть свои собственные специальные методы; например, экземпляры Element
и Document
имеют метод для поиска всех дочерних элементов с заданным именем тега. Продолжая предыдущий пример из 2 строк:
perslist = doc.getElementsByTagName( 'PERSONA' )
print perslist[0].toxml()
print perslist[1].toxml()
Для XML-файла Hamlet в приведенных выше нескольких строках выводятся:
<PERSONA>CLAUDIUS, king of Denmark. </PERSONA>
<PERSONA>HAMLET, son to the late, and nephew to the present king.</PERSONA>
Корневой элемент документа доступен как doc.documentElement
, а его дочерние элементы можно легко изменить, удалив, добавив или удалив узлы:
root = doc.documentElement
# Remove the first child
root.removeChild( root.childNodes[0] )
# Move the new first child to the end
root.appendChild( root.childNodes[0] )
# Insert the new first child (originally,
# the third child) before the 20th child.
root.insertBefore( root.childNodes[0], root.childNodes[20] )
И снова я отсылаю вас к документации по Python для получения полного списка различных классов Node
и их различных методов.
Связь с PyXML¶
Группа специалистов по XML уже некоторое время работает над кодом Python, связанным с XML. Ее дистрибутив под названием PyXML доступен на веб-страницах SIG по адресу https://www.python.org/community/sigs/current/xml-sig. В дистрибутиве PyXML также использовалось имя пакета xml
. Если вы писали программы, в которых использовался PyXML, вас, вероятно, интересует его совместимость с пакетом 2.0 xml
.
Ответ заключается в том, что пакет Python 2.0 xml
несовместим с PyXML, но его можно сделать совместимым, установив последнюю версию PyXML. Многие приложения могут обойтись поддержкой XML, которая включена в Python 2.0, но для более сложных приложений потребуется установить полный пакет PyXML. После установки PyXML версии 0.6.0 или выше заменит пакет xml
, поставляемый с Python, и станет строгим дополнением к стандартному пакету, добавляя множество дополнительных функций. Некоторые из дополнительных функций в PyXML включают:
4 DOM, полноценная реализация DOM от FourThought, Inc.
Проверяющий синтаксический анализатор xmlproc, написанный Ларсом Мариусом Гаршолом.
Модуль ускорителя синтаксического анализа
sgmlop
, написанный Фредриком Лундом.
Изменения в модуле¶
В обширную стандартную библиотеку Python было внесено множество улучшений и исправлений ошибок; некоторые из затронутых модулей включают readline
, ConfigParser
, cgi
, calendar
, posix
, readline
, xmllib
, aifc
, chunk
, wave
, random
, shelve
, и nntplib
. Обратитесь к журналам CVS для получения точной информации о каждом отдельном патче.
Брайан Гэлью внес свой вклад в поддержку OpenSSL для модуля socket
. OpenSSL - это реализация Secure Socket Layer, которая шифрует данные, передаваемые через сокет. При компиляции Python вы можете отредактировать Modules/Setup
, чтобы включить поддержку SSL, что добавляет дополнительную функцию в модуль socket
: socket.ssl(socket, keyfile, certfile)
, которая принимает объект socket и возвращает SSL-сокет. Модули httplib
и urllib
также были изменены для поддержки URL-адресов https://
, хотя никто не реализовал FTP или SMTP через SSL.
Модуль httplib
был переписан Грегом Стайном для поддержки HTTP/1.1.
Предусмотрена обратная совместимость с версией httplib
версии 1.5, хотя использование функций HTTP/1.1, таких как конвейерная обработка, потребует переписывания кода для использования другого набора интерфейсов.
Модуль Tkinter
теперь поддерживает Tcl/Tk версии 8.1, 8.2 или 8.3, а поддержка более старых версий 7.x была прекращена. Модуль Tkinter теперь поддерживает отображение строк в кодировке Unicode в виджетах Tk. Кроме того, Фредрик Лунд внес свой вклад в оптимизацию, которая значительно ускоряет такие операции, как create_line
и create_polygon
, особенно при использовании большого количества координат.
Модуль curses
был значительно расширен, начиная с усовершенствованной версии Оливера Андрича, чтобы обеспечить множество дополнительных функций из ncurses и SYSV curses, таких как цвет, поддержка альтернативного набора символов, пэдов и мыши. Это означает, что модуль больше не совместим с операционными системами, поддерживающими только BSD curses, но, похоже, в настоящее время не существует поддерживаемых операционных систем, которые подпадают под эту категорию.
Как упоминалось в предыдущем обсуждении поддержки Unicode в версии 2.0, была изменена базовая реализация регулярных выражений, предоставляемых модулем re
. ARE, новый движок регулярных выражений, написанный Фредриком Лундом и частично финансируемый Hewlett Packard, поддерживает сопоставление как с 8-битными строками, так и со строками в Юникоде.
Новые модули¶
Был добавлен ряд новых модулей. Мы просто перечислим их с кратким описанием; подробности о конкретном модуле можно найти в документации версии 2.0.
atexit
: Для регистрации функций, которые будут вызываться перед завершением работы интерпретатора Python. Код, который в настоящее время устанавливаетsys.exitfunc
напрямую, следует изменить, чтобы вместо этого использовать модульatexit
, импортируяatexit
и вызываяatexit.register()
с функцией, которая будет вызвана при выходе. (Автор: Скип Монтанаро.)codecs
,encodings
,unicodedata
: Добавлено в рамках новой поддержки Unicode.filecmp
: Заменяет старые модулиcmp
,cmpcache
иdircmp
, которые теперь считаются устаревшими. (Авторы Гордон Макмиллан и Моше Цадка).gettext
: Этот модуль обеспечивает поддержку интернационализации (I18N) и локализации (L10N) программ на Python, предоставляя интерфейс к библиотеке каталога сообщений GNU gettext. (Составлено Барри Уоршоу на основе отдельных материалов Мартина фон Левиса, Питера Фанка и Джеймса Хенстриджа.)linuxaudiodev
: Поддержка устройства/dev/audio
в Linux, аналогичного существующему модулюsunaudiodev
. (Автор - Питер Бош, исправления - Джереми Хилтон.)mmap
: Интерфейс для файлов, отображаемых в памяти, как в Windows, так и в Unix. Содержимое файла может быть отображено непосредственно в память, и в этот момент оно ведет себя как изменяемая строка, поэтому его содержимое можно считывать и изменять. Они могут быть даже переданы функциям, которые ожидают обычные строки, таким как модульre
. (Автор - Сэм Рашинг, некоторые дополнения - А.М. Кухлинг).pyexpat
: Интерфейс к XML-анализатору Expat. (Автор - Пол Прескод).robotparser
: Проанализируйте файлrobots.txt
, который используется для написания веб-пауков, вежливо избегающих определенных областей веб-сайта. Синтаксический анализатор принимает содержимое файлаrobots.txt
, создает на его основе набор правил и затем может отвечать на вопросы о доступности данного URL-адреса. (Автор - Скип Монтанаро.)tabnanny
: Модуль/скрипт для проверки исходного кода Python на наличие неоднозначных отступов. (Автор - Тим Питерс.)UserString
: Базовый класс, полезный для получения объектов, которые ведут себя как строки.webbrowser
: Модуль, который предоставляет независимый от платформы способ запуска веб-браузера по определенному URL-адресу. Для каждой платформы различные браузеры опробуются в определенном порядке. Пользователь может изменить, какой браузер будет запущен, установив переменную среды BROWSER. (Первоначально он был вдохновлен исправлением Эрика С. Рэймонда кurllib
, которое добавило аналогичную функциональность, но окончательный модуль взят из кода, первоначально реализованного Фредом Дрейком какTools/idle/BrowserControl.py
, и адаптированного Фредом для стандартной библиотеки.)_winreg
: Интерфейс к реестру Windows._winreg
представляет собой адаптацию функций, которые были частью PythonWin с 1995 года, но теперь добавлены в основной дистрибутив и улучшены для поддержки Unicode._winreg
была написана Биллом Таттом и Марком Хаммондом.zipfile
: Модуль для чтения и записи архивов в формате ZIP. Это архивы, созданные PKZIP в DOS/Windows или zip в Unix, не следует путать с файлами формата gzip (которые поддерживаются модулемgzip
) (предоставлено автор: Джеймс К. Алстром.)imputil
: Модуль, который предоставляет более простой способ написания настраиваемых перехватчиков импорта по сравнению с существующим модулемihooks
. (Реализован Грегом Стайном, по ходу работы много обсуждался python-dev).
Усовершенствования в режиме ОЖИДАНИЯ¶
IDLE - это официальная кроссплатформенная среда разработки Python, написанная с использованием Tkinter. В состав Python 2.0 входит IDLE 0.6, которая добавляет ряд новых функций и улучшений. Неполный список:
Улучшения и оптимизация пользовательского интерфейса, особенно в области подсветки синтаксиса и автоматического создания отступов.
Браузер классов теперь отображает больше информации, например, о функциях верхнего уровня в модуле.
Ширина табуляции теперь настраивается пользователем. При открытии существующего файла на Python IDLE автоматически определяет правила установки отступов и адаптируется к ним.
Теперь существует поддержка вызова браузеров на различных платформах, используемая для открытия документации по Python в браузере.
В IDLE теперь есть командная строка, которая во многом похожа на интерпретатор vanilla Python.
Во многих местах были добавлены подсказки по звонкам.
IDLE теперь можно установить как пакет.
В окне редактора теперь внизу есть строка/столбец.
Три новые команды, выполняемые нажатием клавиши: Проверить модуль (Alt-F5), Импортировать модуль (F5) и запустить скрипт (Ctrl-F5).
Удаленные и устаревшие модули¶
Некоторые модули были удалены, потому что они устарели или потому что теперь есть лучшие способы сделать то же самое. Модуль stdwin
исчез; он предназначался для независимого от платформы оконного инструментария, который больше не разрабатывается.
Несколько модулей были перемещены в подкаталог lib-old
: cmp
, cmpcache
, dircmp
, dump
, find
, grep
, packmail
, poly
, util
, whatsound
, zmod
. Если у вас есть код, который опирается на модуль, который был перемещен в lib-old
, вы можете просто добавить этот каталог в sys.path
, чтобы вернуть их обратно, но вам рекомендуется обновить любой код, который использует эти модули.
Признание¶
Авторы хотели бы поблагодарить следующих людей за внесение предложений по различным вариантам этой статьи: Дэвида Болена, Марка Хаммонда, Грегга Хаузера, Джереми Хилтона, Фредрика Лунда, Детлефа Ланнерта, Ааза Маруха, Скипа Монтанаро, Владимира Марангозова, Тобиаса Ползина, Гвидо ван Россума, Нила Шеменауэра и Расса Шмидта.