Документация Python неофициальный перевод
Содержание страницы

Что нового в Python 3.1What’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 с промежуточными таблицами перевода соответствующего типа.

    (Предложено Georg Brandl; 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() больше не нужна и теперь объявлена устаревшей.

    (Предложено Georg Brandl и Mattias Brändström; 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.

    (Автор: Дерек Морр; bpo-1655 и bpo-1664.)

  • Модуль 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 APIBuild 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 как замена API PyCObject. Основное различие в том, что новый тип имеет чётко определённый интерфейс для передачи информации о типобезопасности и менее сложную сигнатуру для вызова деструктора. Старый тип имел проблемный API и теперь является устаревшим.

    (Автор: Larry Hastings; bpo-5630.)

Перенос на Python 3.1Porting 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. Подробнее см. обсуждение выше.