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

Что нового в Python 3.1What’s New In Python 3.1

Автор:Рэймонд Хеттингер

В этой статье описываются новые возможности Python 3.1 по сравнению с 3.0.

PEP 372: Упорядоченные словариPEP 372: Ordered Dictionaries

Обычные словари Python перебирают пары ключ/значение в произвольном порядке. За эти годы многие авторы создавали альтернативные реализации, которые запоминают порядок вставки ключей. Основываясь на опыте этих реализаций, был введён новый класс collections.OrderedDict.

API OrderedDict в основном такой же, как у обычных словарей, но гарантированно перебирает ключи и значения в порядке, зависящем от времени первой вставки ключа. Если новая запись перезаписывает существующую, исходная позиция вставки остаётся неизменной. Удаление записи и повторная вставка перемещает её в конец.

Стандартная библиотека теперь поддерживает использование упорядоченных словарей в нескольких модулях. Модуль configparser использует их по умолчанию. Это позволяет читать, изменять и затем записывать конфигурационные файлы в их исходном порядке. Метод _asdict() для collections.namedtuple() теперь возвращает упорядоченный словарь, в котором значения отображаются в том же порядке, что и индексы исходного кортежа. Модуль json дорабатывается с помощью object_pairs_hook, чтобы декодер мог создавать упорядоченные словари. Также добавлена поддержка сторонних инструментов, таких как PyYAML.

См. также

PEP 372 - Упорядоченные словари
PEP написан Армином Ронахером и Реймондом Хеттингером. Реализация написана Реймондом Хеттингером.

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. (Предложение и начальный патч от Andy Chu; доработанный патч от Phillip J. Eby и Nick Coghlan; issue 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
    

    (Авторы: Fredrik Johansson, Victor Stinner, Raymond Hettinger и Mark Dickinson; issue 3439.)

  • Поля в строках format() теперь могут нумероваться автоматически:

    >>> 'Sir {} of {}'.format('Gallahad', 'Camelot')
    'Sir Gallahad of Camelot'
    

    Раньше строка требовала нумерованных полей, например: 'Sir {0} of {1}'.

    (Автор: Eric Smith; issue 5237.)

  • Функция string.maketrans() устарела и заменена новыми статическими методами bytes.maketrans() и bytearray.maketrans(). Это изменение устраняет путаницу в том, какие типы поддерживаются модулем string. Теперь str, bytes и bytearray имеют свои собственные методы maketrans и translate с промежуточными таблицами перевода соответствующего типа.

    (Автор: Georg Brandl; issue 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; issue 4707.)

  • Теперь Python использует алгоритм Дэвида Гея (David Gay) для поиска кратчайшего представления числа с плавающей запятой, которое не меняет его значения. Это должно помочь уменьшить путаницу, связанную с двоичными числами с плавающей запятой.

    Значение легко увидеть на примере числа 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; issue 1580)

Новые, улучшенные и устаревшие модулиNew, Improved, and Deprecated Modules

  • Добавлен класс collections.Counter для удобного подсчёта уникальных элементов в последовательности или итераторе:

    >>> Counter(['red', 'blue', 'red', 'green', 'blue', 'blue'])
    Counter({'blue': 3, 'red': 2, 'green': 1})
    

    (Автор: Raymond Hettinger; issue 1696199.)

  • Добавлен новый модуль tkinter.ttk для доступа к набору тематических виджетов Tk. Основная идея ttk – разделить, насколько это возможно, код, реализующий поведение виджета, и код, реализующий его внешний вид.

    (Автор: Guilherme Polo; issue 2983.)

  • Классы gzip.GzipFile и bz2.BZ2File теперь поддерживают протокол менеджера контекста:

    >>> # Автоматически закрыть файл после записи
    >>> with gzip.GzipFile(filename, "wb") as f:
    ...     f.write(b"xxx")
    

    (Предоставлено Antoine Pitrou.)

  • Модуль decimal теперь поддерживает методы для создания объекта 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; issue 1818.)

  • Функции re.sub(), re.subn() и re.split() теперь принимают параметр flags.

    (Автор: Gregory Smith.)

  • Модуль logging теперь реализует простой класс logging.NullHandler для приложений, которые не используют логирование, но вызывают библиотечный код, который его использует. Установка null-обработчика подавит ложные предупреждения, такие как «No handlers could be found for logger foo»:

    >>> h = logging.NullHandler()
    >>> logging.getLogger("foo").addHandler(h)
    

    (Предложено Vinay Sajip; issue 4384.)

  • Модуль runpy, поддерживающий переключатель командной строки -m, теперь поддерживает выполнение пакетов: при указании имени пакета ищется и выполняется подмодуль __main__.

    (Предложено Andi Vajda; issue 4195.)

  • Модуль pdb теперь может получать доступ и отображать исходный код, загруженный через zipimport (или любой другой совместимый загрузчик PEP 302).

    (Предложено Alexander Belopolsky; issue 4201.)

  • Объекты functools.partial теперь можно упаковывать.

(Предложено Antoine Pitrou и Jesse Noller. Реализовано Jack Diederich; issue 5228.)
  • Добавлены разделы справки pydoc для символов, чтобы help('@') корректно работала в интерактивной среде.

    (Предложено David Laban; issue 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)
    

    (Предложено Ross Light; issue 4285.)

  • Модули nntplib и imaplib теперь поддерживают IPv6.

    (Предложено Derek Morr; issue 1655 и issue 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.

    (Предложено Alexandre Vassalotti и Antoine Pitrou, issue 6137.)

  • Был добавлен новый модуль importlib. Он предоставляет полную, переносимую эталонную реализацию на чистом Python оператора import и его аналога – функции __import__(). Это существенный шаг вперёд в документировании и определении действий, происходящих при импорте.

    (Автор: Бретт Кэннон.)

ОптимизацииOptimizations

Добавлены значительные улучшения производительности:

  • Новая библиотека ввода-вывода (как определено в PEP 3116) была написана в основном на Python и быстро стала проблемным узким местом в Python 3.0. В Python 3.1 эта библиотека была полностью переписана на C и стала работать в 2–20 раз быстрее в зависимости от задачи. Версия на чистом Python всё ещё доступна для экспериментов через модуль _pyio.

    (Авторы: Амори Форжо д'Арк и Антуан Питру.)

  • Добавлена эвристика, благодаря которой кортежи и словари, содержащие только неотслеживаемые объекты, не отслеживаются сборщиком мусора. Это может уменьшить размер коллекций и, следовательно, накладные расходы на сборку мусора в долго работающих программах, в зависимости от используемых типов данных.

    (Предложено Antoine Pitrou, issue 4688.)

  • При включении опции configure --with-computed-gotos на компиляторах, которые её поддерживают (особенно: gcc, SunPro, icc), цикл выполнения байт-кода компилируется с новым механизмом диспетчеризации, который даёт ускорение до 20% в зависимости от системы, компилятора и теста.

    (Предложено Antoine Pitrou совместно с рядом других участников, issue 4753).

  • Декодирование UTF-8, UTF-16 и LATIN-1 теперь в два-четыре раза быстрее.

    (Предложено Antoine Pitrou и Amaury Forgeot d’Arc, issue 4868.)

  • Модуль json теперь содержит расширение на C, существенно повышающее его производительность. Кроме того, API был изменён: json теперь работает только с str, а не с bytes. Это изменение приводит модуль в большее соответствие со спецификацией JSON, которая определяется в терминах Unicode.

    (Предложено Bob Ippolito, портировано на Py3.1 Antoine Pitrou и Benjamin Peterson; issue 4136.)

  • При распаковке имена атрибутов упакованных объектов теперь интернируются. Это экономит память и позволяет уменьшить размер файлов pickle.

    (Предложено Jake McGuire и Antoine Pitrou; issue 5084.)

IDLE

  • Меню «Формат» в IDLE теперь содержит опцию удаления завершающих пробелов из исходного файла.

    (Предложено Roger D. Serwy; issue 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 есть новая опция configure --enable-big-digits, которую можно использовать для переопределения этого значения по умолчанию.

    Помимо улучшений производительности, это изменение должно быть незаметно для конечных пользователей, за одним исключением: для целей тестирования и отладки появился новый sys.int_info, который предоставляет информацию о внутреннем формате, указывая количество бит на цифру и размер в байтах типа C, используемого для хранения каждой цифры:

    >>> import sys
    >>> sys.int_info
    sys.int_info(bits_per_digit=30, sizeof_digit=4)
    

    (Предложено Mark Dickinson; issue 4258.)

  • Функция PyLong_AsUnsignedLongLong() теперь обрабатывает отрицательное pylong, возбуждая OverflowError вместо TypeError.

    (Авторы: Mark Dickinson и Lisandro Dalcrin; issue 5175.)

  • Устарело PyNumber_Int(). Используйте PyNumber_Long().

    (Автор: Mark Dickinson; issue 4910.)

  • Добавлена новая функция PyOS_string_to_double() для замены устаревших функций PyOS_ascii_strtod() и PyOS_ascii_atof().

    (Автор: Mark Dickinson; issue 5914.)

  • Добавлен PyCapsule в качестве замены API PyCObject. Основное отличие в том, что новый тип имеет чётко определённый интерфейс для передачи информации о безопасности типов и менее сложную сигнатуру для вызова деструктора. Старый тип имел проблемный API и теперь устарел.

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

Перенос на Python 3.1Porting to Python 3.1

В этом разделе перечислены ранее описанные изменения и другие исправления ошибок, которые могут потребовать изменений в коде:

  • Новые строковые представления чисел с плавающей запятой могут нарушить существующие доктесты. Например:

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