Содержание страницы
Что нового в Python 3.1¶What’s New In Python 3.1
- Автор:
Raymond Hettinger
В этой статье описываются новые возможности Python 3.1 по сравнению с 3.0. Python 3.1 был выпущен 27 июня 2009 года.
PEP 372: Упорядоченные словари¶PEP 372: Ordered Dictionaries
Обычные словари Python перебирают пары ключ/значение в произвольном порядке.
С годами ряд авторов написали альтернативные реализации,
запоминающие порядок исходной вставки ключей. Основываясь
на опыте этих реализаций, был введён новый класс collections.OrderedDict.
API OrderedDict в основном такой же, как у обычных словарей, но гарантированно перебирает ключи и значения в порядке, зависящем от времени первой вставки ключа. Если новая запись перезаписывает существующую, исходная позиция вставки остаётся неизменной. Удаление записи и повторная вставка перемещает её в конец.
Стандартная библиотека теперь поддерживает использование упорядоченных словарей в нескольких модулях. Модуль configparser использует их по умолчанию. Это позволяет читать, изменять и затем записывать конфигурационные файлы в исходном порядке. Метод _asdict() для collections.namedtuple() теперь возвращает упорядоченный словарь, в котором значения располагаются в том же порядке, что и индексы базового кортежа. Модуль json дополняется параметром object_pairs_hook, позволяющим декодеру строить упорядоченные словари. Также добавлена поддержка сторонних инструментов, таких как PyYAML.
См. также
- PEP 372 - Упорядоченные словари
PEP написан Армином Ронахером и Реймондом Хеттингером. Реализация написана Реймондом Хеттингером.
Поскольку упорядоченный словарь запоминает порядок вставки, его можно использовать в сочетании с сортировкой для создания отсортированного словаря:
>>> # обычный неотсортированный словарь
>>> d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}
>>> # словарь, отсортированный по ключу
>>> OrderedDict(sorted(d.items(), key=lambda t: t[0]))
OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])
>>> # словарь, отсортированный по значению
>>> OrderedDict(sorted(d.items(), key=lambda t: t[1]))
OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])
>>> # словарь, отсортированный по длине строки ключа
>>> OrderedDict(sorted(d.items(), key=lambda t: len(t[0])))
OrderedDict([('pear', 1), ('apple', 4), ('orange', 2), ('banana', 3)])
Новые отсортированные словари сохраняют порядок сортировки при удалении записей. Но при добавлении новых ключей они добавляются в конец, и сортировка не сохраняется.
PEP 378: Спецификатор формата для разделителя тысяч¶PEP 378: Format Specifier for Thousands Separator
Встроенная функция format() и метод str.format() используют
мини-язык, который теперь включает простой, не зависящий от локали способ форматирования числа с разделителем тысяч. Это позволяет «очеловечить» вывод программы, улучшая его профессиональный вид и читаемость:
>>> format(1234567, ',d')
'1,234,567'
>>> format(1234567.89, ',.2f')
'1,234,567.89'
>>> format(12345.6 + 8901234.12j, ',f')
'12,345.600000+8,901,234.120000j'
>>> format(Decimal('1234567.89'), ',f')
'1,234,567.89'
Поддерживаемые типы: int, float, complex
и decimal.Decimal.
Обсуждаются способы указания альтернативных разделителей, таких как точки, пробелы, апострофы или подчёркивания. Приложения, учитывающие локаль, должны использовать существующий спецификатор формата n, который уже имеет некоторую поддержку разделителей тысяч.
См. также
- PEP 378 - Спецификатор формата для разделителя тысяч
PEP написан Реймондом Хеттингером, реализован Эриком Смитом и Марком Дикинсоном.
Другие изменения языка¶Other Language Changes
Некоторые более мелкие изменения в ядре языка Python:
Каталоги и zip-архивы, содержащие файл
__main__.py, теперь можно выполнять напрямую, передавая их имя интерпретатору. Каталог/zip-файл автоматически вставляется как первая запись в sys.path. (Предложение и начальный патч: Энди Чу; доработанный патч: Филлип Дж. Эби и Ник Коглан; bpo-1739468.)Тип
int()получил методbit_length, который возвращает количество битов, необходимое для представления своего аргумента в двоичном виде:>>> n = 37 >>> bin(37) '0b100101' >>> n.bit_length() 6 >>> n = 2**123-1 >>> n.bit_length() 123 >>> (n+1).bit_length() 124
(Авторы: Фредрик Йоханссон, Виктор Стиннер, Реймонд Хеттингер и Марк Дикинсон; bpo-3439.)
Поля в строках
format()теперь могут автоматически нумероваться:>>> 'Sir {} of {}'.format('Gallahad', 'Camelot') 'Sir Gallahad of Camelot'
Раньше строка требовала нумерованных полей, например:
'Sir {0} of {1}'.(Автор: Эрик Смит; bpo-5237.)
Функция
string.maketrans()объявлена устаревшей и заменяется новыми статическими методамиbytes.maketrans()иbytearray.maketrans(). Это изменение устраняет путаницу относительно того, какие типы поддерживаются модулемstring. Теперьstr,bytesиbytearrayимеют собственные методы maketrans и translate с промежуточными таблицами перевода соответствующего типа.(Автор: Георг Брандль; bpo-5675.)
Синтаксис оператора
withтеперь позволяет использовать несколько контекстных менеджеров в одном операторе:>>> with open('mylog.txt') as infile, open('a.out', 'w') as outfile: ... for line in infile: ... if '<critical>' in line: ... outfile.write(line)
С новым синтаксисом функция
contextlib.nested()больше не нужна и теперь объявлена устаревшей.(Авторы: Георг Брандль и Маттиас Брэндстрём; appspot issue 53094.)
round(x, n)теперь возвращает целое число, если x – целое. Ранее возвращалось число с плавающей запятой:>>> round(1123, -2) 1100
(Автор: Mark Dickinson; bpo-4707.)
Python теперь использует алгоритм Дэвида Гея для поиска кратчайшего представления числа с плавающей запятой, не изменяющего его значение. Это должно помочь уменьшить некоторую путаницу, связанную с двоичными числами с плавающей запятой.
Значение хорошо видно на примере числа
1.1, которое не имеет точного эквивалента в двоичной арифметике с плавающей запятой. Поскольку точного эквивалента нет, выражениеfloat('1.1')вычисляется как ближайшее представимое значение, которое равно0x1.199999999999ap+0в шестнадцатеричной записи или1.100000000000000088817841970012523233890533447265625в десятичной. Это ближайшее значение использовалось и продолжает использоваться в последующих вычислениях с плавающей запятой.Новшество заключается в том, как число отображается. Раньше Python использовал простой подход. Значение
repr(1.1)вычислялось какformat(1.1, '.17g'), что давало'1.1000000000000001'. Преимущество использования 17 знаков заключалось в том, что оно опиралось на гарантии IEEE-754, обеспечивающие, чтоeval(repr(1.1))при обратном преобразовании даст исходное значение. Недостаток в том, что многие находили такой вывод запутанным (принимая внутренние ограничения двоичного представления чисел с плавающей запятой за проблему самого Python).Новый алгоритм для
repr(1.1)умнее и возвращает'1.1'. По сути, он ищет все эквивалентные строковые представления (те, которые сохраняются с тем же базовым значением float) и возвращает кратчайшее представление.Новый алгоритм стремится выдавать более чистые представления, когда это возможно, но не изменяет базовые значения. Поэтому по-прежнему верно, что
1.1 + 2.2 != 3.3, даже если представления могут намекать на обратное.Новый алгоритм зависит от определённых возможностей базовой реализации чисел с плавающей запятой. Если необходимые возможности отсутствуют, будет продолжать использоваться старый алгоритм. Кроме того, текстовые протоколы pickle обеспечивают кроссплатформенную переносимость за счёт использования старого алгоритма.
(Авторы: Eric Smith и Mark Dickinson; bpo-1580)
Новые, улучшенные и устаревшие модули¶New, Improved, and Deprecated Modules
Добавлен класс
collections.Counterдля удобного подсчёта уникальных элементов в последовательности или итерируемом объекте:>>> Counter(['red', 'blue', 'red', 'green', 'blue', 'blue']) Counter({'blue': 3, 'red': 2, 'green': 1})
(Автор: Raymond Hettinger; bpo-1696199.)
Добавлен новый модуль
tkinter.ttkдля доступа к набору темизированных виджетов Tk. Основная идея ttk – разделить, насколько это возможно, код, реализующий поведение виджета, и код, реализующий его внешний вид.(Автор: Guilherme Polo; bpo-2983.)
Классы
gzip.GzipFileиbz2.BZ2Fileтеперь поддерживают протокол менеджера контекста:>>> # Автоматически закрыть файл после записи >>> with gzip.GzipFile(filename, "wb") as f: ... f.write(b"xxx")
(Автор: Antoine Pitrou.)
Модуль
decimalтеперь поддерживает методы создания десятичного объекта из двоичногоfloat. Преобразование является точным, но иногда может быть неожиданным:>>> Decimal.from_float(1.1) Decimal('1.100000000000000088817841970012523233890533447265625')
Длинный десятичный результат показывает фактическую двоичную дробь, хранящуюся для 1.1. Дробь имеет много цифр, потому что 1.1 не может быть точно представлена в двоичном виде.
(Авторы: Raymond Hettinger и Mark Dickinson.)
Модуль
itertoolsобзавёлся двумя новыми функциями. Функцияitertools.combinations_with_replacement()– одна из четырёх для генерации комбинаторных объектов, включая перестановки и декартовы произведения. Функцияitertools.compress()имитирует своего тёзку из APL. Кроме того, существующая функцияitertools.count()теперь имеет необязательный аргумент step и может принимать любой тип счётной последовательности, включаяfractions.Fractionиdecimal.Decimal:>>> [p+q for p,q in combinations_with_replacement('LOVE', 2)] ['LL', 'LO', 'LV', 'LE', 'OO', 'OV', 'OE', 'VV', 'VE', 'EE'] >>> list(compress(data=range(10), selectors=[0,0,1,1,0,1,0,1,0,0])) [2, 3, 5, 7] >>> c = count(start=Fraction(1,2), step=Fraction(1,6)) >>> [next(c), next(c), next(c), next(c)] [Fraction(1, 2), Fraction(2, 3), Fraction(5, 6), Fraction(1, 1)]
(Автор: Raymond Hettinger.)
collections.namedtuple()теперь поддерживает именованный аргумент rename, который позволяет автоматически преобразовывать недопустимые имена полей в позиционные имена вида _0, _1 и т.д. Это полезно, когда имена полей создаются внешним источником, например заголовком CSV, списком полей SQL или пользовательским вводом:>>> query = input() SELECT region, dept, count(*) FROM main GROUPBY region, dept >>> cursor.execute(query) >>> query_fields = [desc[0] for desc in cursor.description] >>> UserQuery = namedtuple('UserQuery', query_fields, rename=True) >>> pprint.pprint([UserQuery(*row) for row in cursor]) [UserQuery(region='South', dept='Shipping', _2=185), UserQuery(region='North', dept='Accounting', _2=37), UserQuery(region='West', dept='Sales', _2=419)]
(Автор: Raymond Hettinger; bpo-1818.)
Функции
re.sub(),re.subn()иre.split()теперь принимают параметр flags.(Автор: Gregory Smith.)
Модуль
loggingтеперь реализует простой классlogging.NullHandlerдля приложений, которые не используют логирование, но вызывают библиотечный код, который его использует. Настройка нулевого обработчика подавит ложные предупреждения, такие как «No handlers could be found for logger foo»:>>> h = logging.NullHandler() >>> logging.getLogger("foo").addHandler(h)
(Автор: Vinay Sajip; bpo-4384).
Модуль
runpy, который поддерживает ключ командной строки-m, теперь поддерживает выполнение пакетов: при указании имени пакета ищется и выполняется подмодуль__main__.(Автор: Andi Vajda; bpo-4195.)
Модуль
pdbтеперь может получать доступ и отображать исходный код, загруженный черезzipimport(или любой другой совместимый загрузчик PEP 302).(Автор: Alexander Belopolsky; bpo-4201.)
Объекты
functools.partialтеперь можно упаковывать с помощью pickle.
(Предложено Антуаном Питру и Джесси Ноллером. Реализовано Джеком Дидерихом; bpo-5228.)
Добавлены темы справки
pydocдля символов, чтобыhelp('@')работала в интерактивной среде как ожидается.(Автор: Дэвид Лабан; bpo-4739.)
Модуль
unittestтеперь поддерживает пропуск отдельных тестов или классов тестов. А также поддерживает пометку теста как ожидаемого сбоя – теста, который заведомо не работает, но не должен учитываться как ошибка в TestResult:class TestGizmo(unittest.TestCase): @unittest.skipUnless(sys.platform.startswith("win"), "requires Windows") def test_gizmo_on_windows(self): ... @unittest.expectedFailure def test_gimzo_without_required_library(self): ...
Кроме того, тесты для исключений были расширены для работы с контекстными менеджерами с помощью оператора
with:def test_division_by_zero(self): with self.assertRaises(ZeroDivisionError): x / 0
Кроме того, было добавлено несколько новых методов утверждений, включая
assertSetEqual(),assertDictEqual(),assertDictContainsSubset(),assertListEqual(),assertTupleEqual(),assertSequenceEqual(),assertRaisesRegexp(),assertIsNone()иassertIsNotNone().(Авторы: Бенджамин Петерсон и Антуан Питру.)
Модуль
ioсодержит три новые константы для методаseek():SEEK_SET,SEEK_CURиSEEK_END.Кортеж
sys.version_infoтеперь является именованным кортежем:>>> sys.version_info sys.version_info(major=3, minor=1, micro=0, releaselevel='alpha', serial=2)
(Автор: Росс Лайт; bpo-4285.)
Модули
nntplibиimaplibтеперь поддерживают IPv6.Модуль
pickleбыл адаптирован для лучшей совместимости с Python 2.x при использовании протокола 2 и ниже. Реорганизация стандартной библиотеки изменила формальные ссылки на многие объекты. Например,__builtin__.setв Python 2 называетсяbuiltins.setв Python 3. Это изменение затрудняло обмен данными между разными версиями Python. Но теперь, когда выбран протокол 2 или ниже, pickler будет автоматически использовать старые имена Python 2 как для загрузки, так и для выгрузки. Это переназначение включено по умолчанию, но может быть отключено с помощью опции fix_imports :>>> s = {1, 2, 3} >>> pickle.dumps(s, protocol=0) b'c__builtin__\nset\np0\n((lp1\nL1L\naL2L\naL3L\natp2\nRp3\n.' >>> pickle.dumps(s, protocol=0, fix_imports=False) b'cbuiltins\nset\np0\n((lp1\nL1L\naL2L\naL3L\natp2\nRp3\n.'
Неприятным, но неизбежным побочным эффектом этого изменения является то, что протокол 2 pickles, созданные Python 3.1, не будут читаться в Python 3.0. Последний протокол pickle, протокол 3, следует использовать при переносе данных между реализациями Python 3.x, так как он не пытается сохранять совместимость с Python 2.x.
(Авторы: Александр Вассалотти и Антуан Питру, bpo-6137.)
Добавлен новый модуль
importlib. Он предоставляет полную, переносимую, эталонную реализацию на чистом Python оператораimportи его аналога – функции__import__(). Это представляет собой существенный шаг вперёд в документировании и определении действий, происходящих во время импорта.(Автор: Бретт Кэннон.)
Оптимизации¶Optimizations
Добавлены значительные улучшения производительности:
Новая библиотека ввода-вывода (определённая в PEP 3116) была в основном написана на Python и быстро показала себя как проблемное узкое место в Python 3.0. В Python 3.1 библиотека ввода-вывода была полностью переписана на C и работает в 2–20 раз быстрее в зависимости от задачи. Версия на чистом Python по-прежнему доступна для экспериментов через модуль
_pyio.(Авторы: Амори Форжо д'Арк и Антуан Питру.)
Добавлена эвристика, благодаря которой кортежи и словари, содержащие только неотслеживаемые объекты, не отслеживаются сборщиком мусора. Это может уменьшить размер коллекций и, следовательно, накладные расходы на сборку мусора в долго работающих программах, в зависимости от используемых типов данных.
(Автор: Антуан Питру, bpo-4688.)
При включении опции configure с именем
--with-computed-gotosна компиляторах, которые её поддерживают (в частности: gcc, SunPro, icc), цикл выполнения байт-кода компилируется с новым механизмом диспетчеризации, что даёт прирост производительности до 20% в зависимости от системы, компилятора и теста.(Автор: Антуан Питру совместно с рядом других участников, bpo-4753).
Декодирование UTF-8, UTF-16 и LATIN-1 теперь в два-четыре раза быстрее.
(Авторы: Антуан Питру и Амори Форжо д'Арк, bpo-4868.)
Модуль
jsonтеперь имеет расширение на C для существенного повышения его производительности. Кроме того, API был изменён так, что json работает только сstr, а не сbytes. Это изменение делает модуль более соответствующим спецификации JSON, которая определена в терминах Unicode.(Автор: Боб Ипполито, адаптировано для Py3.1 Антуаном Питру и Бенджамином Петерсоном; bpo-4136.)
При распаковке имена атрибутов упакованных объектов теперь интернируются. Это экономит память и позволяет уменьшить размер файлов pickle.
(Авторы: Джейк МакГуайр и Антуан Питру; bpo-5084.)
IDLE¶
Меню «Формат» в IDLE теперь содержит опцию удаления завершающих пробелов из исходного файла.
(Автор: Roger D. Serwy; bpo-5150.)
Изменения в сборке и C API¶Build and C API Changes
Изменения процесса сборки Python и C API включают:
Целые числа теперь хранятся внутри либо по основанию
2**15, либо по основанию2**30, причём основание выбирается во время сборки. Ранее они всегда хранились по основанию2**15. Использование основания2**30даёт значительное улучшение производительности на 64-битных машинах, но результаты бенчмарков на 32-битных машинах неоднозначны. Поэтому по умолчанию на 64-битных машинах используется основание2**30, а на 32-битных – основание2**15; в Unix есть новая опция конфигурации--enable-big-digits, позволяющая переопределить это поведение.За исключением улучшения производительности, это изменение должно быть незаметно для конечных пользователей, за одним исключением: для целей тестирования и отладки появилась новая
sys.int_info, предоставляющая информацию о внутреннем формате: количество бит на разряд и размер в байтах типа C, используемого для хранения каждого разряда:>>> import sys >>> sys.int_info sys.int_info(bits_per_digit=30, sizeof_digit=4)
(Автор: Mark Dickinson; bpo-4258.)
Функция
PyLong_AsUnsignedLongLong()теперь обрабатывает отрицательное pylong, вызываяOverflowErrorвместоTypeError.(Автор: Mark Dickinson и Lisandro Dalcrin; bpo-5175.)
Устарело
PyNumber_Int(). Вместо этого используйтеPyNumber_Long().(Автор: Mark Dickinson; bpo-4910.)
Добавлена новая функция
PyOS_string_to_double(), заменяющая устаревшие функцииPyOS_ascii_strtod()иPyOS_ascii_atof().(Автор: Mark Dickinson; bpo-5914.)
Добавлен
PyCapsuleкак замена APIPyCObject. Основное различие в том, что новый тип имеет чётко определённый интерфейс для передачи информации о типобезопасности и менее сложную сигнатуру для вызова деструктора. Старый тип имел проблемный API и теперь является устаревшим.(Автор: Larry Hastings; bpo-5630.)
Перенос на Python 3.1¶Porting to Python 3.1
В этом разделе перечислены ранее описанные изменения и другие исправления ошибок, которые могут потребовать изменений в коде:
Новые строковые представления чисел с плавающей запятой могут нарушить существующие doctest. Например:
def e(): '''Вычислить основание натуральных логарифмов. >>> e() 2.7182818284590451 ''' return sum(1/math.factorial(x) for x in reversed(range(30))) doctest.testmod() ********************************************************************** Failed example: e() Expected: 2.7182818284590451 Got: 2.718281828459045 **********************************************************************
Автоматическое переименование имён в модуле pickle для протокола 2 и ниже может сделать pickle-файлы Python 3.1 нечитаемыми в Python 3.0. Одно из решений – использовать протокол 3. Другое решение – установить опцию fix_imports в
False. Подробнее см. обсуждение выше.