# Що нового в Python 3.1

Автор:

  Raymond Hettinger

У цій статті пояснюється нові функції в Python 3.1 порівняно з 3.0. Python 3.1 було випущено 27 червня 2009 року.

## PEP 372: Упорядковані словники

Звичайні словники Python перебирають пари ключ/значення в довільному порядку. Протягом багатьох років кілька авторів написали альтернативні реалізації, які запам’ятовують порядок початкового вставлення ключів. На основі досвіду цих реалізацій було введено новий клас `collections.OrderedDict`.

API OrderedDict практично такий же, як і звичайні словники, але перебиратиме ключі та значення в гарантованому порядку залежно від того, коли ключ було вперше вставлено. Якщо новий запис перезаписує існуючий запис, початкова позиція вставки залишається незмінною. Видалення запису та його повторне вставлення перемістить його в кінець.

The standard library now supports use of ordered dictionaries in several modules. The `configparser` module uses them by default. This lets configuration files be read, modified, and then written back in their original order. The _asdict() method for `collections.namedtuple()` now returns an ordered dictionary with the values appearing in the same order as the underlying tuple indices. The `json` module is being built-out with an object_pairs_hook to allow OrderedDicts to be built by the decoder. Support was also added for third-party tools like PyYAML.

Дивись також

PEP 372 - Впорядковані словники

  PEP, автори Армін Роначер і Раймонд Геттінгер. Реалізацію написав Раймонд Хеттінгер.

Since an ordered dictionary remembers its insertion order, it can be used in conjunction with sorting to make a sorted dictionary:

    >>> # regular unsorted dictionary
    >>> d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}

    >>> # dictionary sorted by key
    >>> OrderedDict(sorted(d.items(), key=lambda t: t[0]))
    OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])

    >>> # dictionary sorted by value
    >>> OrderedDict(sorted(d.items(), key=lambda t: t[1]))
    OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])

    >>> # dictionary sorted by length of the key string
    >>> OrderedDict(sorted(d.items(), key=lambda t: len(t[0])))
    OrderedDict([('pear', 1), ('apple', 4), ('orange', 2), ('banana', 3)])

The new sorted dictionaries maintain their sort order when entries are deleted. But when new keys are added, the keys are appended to the end and the sort is not maintained.

## PEP 378: Специфікатор формату для розділювача тисяч

Вбудована функція `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, написаний Реймондом Геттінгером і реалізований Еріком Смітом і Марком Дікінсоном.

## Інші зміни мови

Деякі менші зміни, внесені до основної мови 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.)

- The `string.maketrans()` function is deprecated and is replaced by new static methods, `bytes.maketrans()` and `bytearray.maketrans()`. This change solves the confusion around which types were supported by the `string` module. Now, `str`, `bytes`, and `bytearray` each have their own maketrans and translate methods with intermediate translation tables of the appropriate type.

  (Надав Георг Брандл; 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)

  With the new syntax, the `contextlib.nested()` function is no longer needed and is now deprecated.

  (Надано Георгом Брандлом і Маттіасом Брендстремом; appspot issue 53094.)

- `round(x, n)` тепер повертає ціле число, якщо x є цілим числом. Раніше він повертав float:

      >>> round(1123, -2)
      1100

  (Надав Марк Дікінсон; bpo-4707.)

- Python now uses David Gay’s algorithm for finding the shortest floating point representation that doesn’t change its value. This should help mitigate some of the confusion surrounding binary floating point numbers.

  The significance is easily seen with a number like `1.1` which does not have an exact equivalent in binary floating point. Since there is no exact equivalent, an expression like `float('1.1')` evaluates to the nearest representable value which is `0x1.199999999999ap+0` in hex or `1.100000000000000088817841970012523233890533447265625` in decimal. That nearest value was and still is used in subsequent floating point calculations.

  What is new is how the number gets displayed. Formerly, Python used a simple approach. The value of `repr(1.1)` was computed as `format(1.1, '.17g')` which evaluated to `'1.1000000000000001'`. The advantage of using 17 digits was that it relied on IEEE-754 guarantees to assure that `eval(repr(1.1))` would round-trip exactly to its original value. The disadvantage is that many people found the output to be confusing (mistaking intrinsic limitations of binary floating point representation as being a problem with Python itself).

  Новий алгоритм для `repr(1.1)` розумніший і повертає `'1.1'`. По суті, він шукає всі еквівалентні представлення рядків (ті, які зберігаються з тим самим базовим значенням з плаваючою точкою) і повертає найкоротше представлення.

  Новий алгоритм має тенденцію видавати чіткіші представлення, коли це можливо, але він не змінює основні значення. Таким чином, це все ще так, що `1.1 + 2.2 != 3.3`, навіть якщо представлення можуть припускати інше.

  The new algorithm depends on certain features in the underlying floating point implementation. If the required features are not found, the old algorithm will continue to be used. Also, the text pickle protocols assure cross-platform portability by using the old algorithm.

  (Надано Еріком Смітом і Марком Дікінсоном; bpo-1580)

## Нові, покращені та застарілі модулі

- Додано клас `collections.Counter` для підтримки зручного підрахунку унікальних елементів у послідовності або ітерації:

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

  (Надав Реймонд Геттінгер; bpo-1696199.)

- Додано новий модуль `tkinter.ttk` для доступу до набору тематичних віджетів Tk. Основна ідея ttk полягає в тому, щоб відокремити, наскільки це можливо, код, що реалізує поведінку віджета, від коду, що реалізує його зовнішній вигляд.

  (Надав Гільєрме Поло; bpo-2983.)

- Класи `gzip.GzipFile` і `bz2.BZ2File` тепер підтримують протокол керування контекстом:

      >>> # Automatically close file after writing
      >>> with gzip.GzipFile(filename, "wb") as f:
      ...     f.write(b"xxx")

  (Надав Антуан Пітру.)

- Модуль `decimal` тепер підтримує методи для створення десяткового об’єкта з двійкового `float`. Перетворення точне, але іноді може бути несподіваним:

      >>> Decimal.from_float(1.1)
      Decimal('1.100000000000000088817841970012523233890533447265625')

  Довгий десятковий результат показує фактичний двійковий дріб, який зберігається для 1,1. Дріб має багато цифр, оскільки 1.1 не може бути точно представлений у двійковому вигляді.

  (Надано Реймондом Геттінгером і Марком Дікінсоном.)

- Модуль `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)]

  (Надав Реймонд Геттінгер.)

- `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)]

  (Надав Раймонд Геттінгер; bpo-1818.)

- Функції `re.sub()`, `re.subn()` і `re.split()` тепер приймають параметр flags.

  (Надав Грегорі Сміт.)

- Модуль `logging` тепер реалізує простий клас `logging.NullHandler` для програм, які не використовують журналювання, але викликають код бібліотеки, який це робить. Налаштування нульового обробника придушить фальшиві попередження, такі як «Не вдалося знайти обробників для logger foo»:

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

  (Надав Віней Саджип; bpo-4384).

- Модуль `runpy`, який підтримує перемикач командного рядка `-m`, тепер підтримує виконання пакетів шляхом пошуку та виконання субмодуля `__main__`, коли надається ім’я пакета.

  (Надав Анді Вайда; bpo-4195.)

- Модуль `pdb` тепер може отримувати доступ і відображати вихідний код, завантажений через `zipimport` (або будь-який інший відповідний завантажувач PEP 302).

  (Надав Олександр Бєлопольський; bpo-4201.)

- `functools.partial` об’єкти тепер можна маринувати.

> (Запропоновано Антуаном Пітру та Джессі Ноллером. Реалізовано Джеком Дідеріхом; 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

  In addition, several new assertion methods were added including `assertSetEqual()`, `assertDictEqual()`, `assertDictContainsSubset()`, `assertListEqual()`, `assertTupleEqual()`, `assertSequenceEqual()`, `assertRaisesRegexp()`, `assertIsNone()`, and `assertIsNotNone()`.

  (Надано Бенджаміном Петерсоном і Антуаном Пітру.)

- The `io` module has three new constants for the `seek()` method: `SEEK_SET`, `SEEK_CUR`, and `SEEK_END`.

- The `sys.version_info` tuple is now a named tuple:

      >>> sys.version_info
      sys.version_info(major=3, minor=1, micro=0, releaselevel='alpha', serial=2)

  (Надав Росс Лайт; bpo-4285.)

- The `nntplib` and `imaplib` modules now support IPv6.

  (Надав Дерек Морр; bpo-1655 і bpo-1664.)

- Модуль `pickle` було адаптовано для кращої сумісності з Python 2.x при використанні протоколу 2 або нижчого. Реорганізація стандартної бібліотеки змінила формальне посилання для багатьох об’єктів. Наприклад, `__builtin__.set` у Python 2 називається `builtins.set` у Python 3. Ця зміна збентежила спроби обмінюватися даними між різними версіями Python. Але тепер, коли вибрано протокол 2 або нижчий, піклер автоматично використовуватиме старі назви 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, створені Python 3.1, не можна буде прочитати з Python 3.0. Найновіший протокол pickle, протокол 3, слід використовувати під час переміщення даних між реалізаціями Python 3.x, оскільки він не намагається зберегти сумісність із Python 2.x.

  (Надано Александром Вассалотті та Антуаном Пітру, bpo-6137.)

- Додано новий модуль `importlib`. Він забезпечує повну, портативну, чисту довідкову реалізацію на Python оператора `import` і його відповідника, функції `__import__()`. Це значний крок вперед у документуванні та визначенні дій, які відбуваються під час імпорту.

  (Надав Бретт Кеннон.)

## Оптимізації

Додано основні покращення продуктивності:

- Нова бібліотека введення-виведення (як визначено в PEP 3116) була здебільшого написана на Python і швидко виявилася проблемним вузьким місцем у Python 3.0. У Python 3.1 бібліотеку вводу/виводу було повністю переписано на C і вона працює від 2 до 20 разів швидше залежно від поставленого завдання. Чиста версія Python все ще доступна для експериментальних цілей через модуль `_pyio`.

  (Надано Аморі Форже д’Арк і Антуаном Пітру.)

- Додано евристику, щоб кортежі та dicts, що містять лише невідстежувані об’єкти, не відстежувалися збирачем сміття. Це може зменшити розмір колекцій і, отже, накладні витрати на збирання сміття в програмах, що працюють довго, залежно від конкретного використання типів даних.

  (Надав Антуан Пітру, bpo-4688.)

- Увімкнувши параметр конфігурації під назвою `--with-computed-gotos` на компіляторах, які його підтримують (зокрема, gcc, SunPro, icc), цикл оцінки байт-коду компілюється з новим механізмом відправки, який забезпечує прискорення до 20% , залежно від системи, компілятора та тесту.

  (Надано Антуаном Пітру та низкою інших учасників, bpo-4753).

- Декодування UTF-8, UTF-16 і LATIN-1 тепер у два-чотири рази швидше.

  (Надано Антуаном Пітру та Аморі Форже д’Арк, bpo-4868.)

- The `json` module now has a C extension to substantially improve its performance. In addition, the API was modified so that json works only with `str`, not with `bytes`. That change makes the module closely match the JSON specification which is defined in terms of Unicode.

  (Надано Бобом Іполіто та перетворено на Py3.1 Антуаном Пітру та Бенджаміном Петерсоном; bpo-4136.)

- Unpickling тепер інтернує назви атрибутів маринованих об’єктів. Це економить пам’ять і дозволяє зробити солоні огірки меншими.

  (Надано Джейком Макгуайром і Антуаном Пітру; bpo-5084.)

## ПРОСТОЮЧИЙ

- Меню форматування IDLE тепер надає можливість видаляти кінцеві пробіли з вихідного файлу.

  (Надав Роджер Д. Серві; bpo-5150.)

## Зміни збірки та C API

Зміни в процесі збирання Python і в API C включають:

- Цілі числа тепер зберігаються внутрішньо або в базі `2**15`, або в базі `2**30`, причому база визначається під час створення. Раніше вони завжди зберігалися в базі `2**15`. Використання бази `2**30` дає значне покращення продуктивності на 64-розрядних машинах, але результати порівняльного тестування на 32-розрядних машинах були неоднозначними. Тому за замовчуванням на 64-розрядних машинах використовується основа `2**30` і основа `2**15` на 32-розрядних машинах; в Unix є новий параметр конфігурації `--enable-big-digits`, який можна використовувати для заміни цього значення за замовчуванням.

  Apart from the performance improvements this change should be invisible to end users, with one exception: for testing and debugging purposes there’s a new `sys.int_info` that provides information about the internal format, giving the number of bits per digit and the size in bytes of the C type used to store each digit:

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

  (Надав Марк Дікінсон; bpo-4258.)

- Функція `PyLong_AsUnsignedLongLong()` тепер обробляє негативний pylong, викликаючи `OverflowError` замість `TypeError`.

  (Надано Марком Дікінсоном і Лісандро Далкріном; bpo-5175.)

- Deprecated `PyNumber_Int()`. Use `PyNumber_Long()` instead.

  (Надав Марк Дікінсон; bpo-4910.)

- Added a new `PyOS_string_to_double()` function to replace the deprecated functions `PyOS_ascii_strtod()` and `PyOS_ascii_atof()`.

  (Надав Марк Дікінсон; bpo-5914.)

- Added `PyCapsule` as a replacement for the `PyCObject` API. The principal difference is that the new type has a well defined interface for passing typing safety information and a less complicated signature for calling a destructor. The old type had a problematic API and is now deprecated.

  (Надав Ларрі Гастінгс; bpo-5630.)

## Перенесення на Python 3.1

У цьому розділі перераховані раніше описані зміни та інші виправлення помилок, які можуть потребувати змін у вашому коді:

- The new floating point string representations can break existing doctests. For example:

      def e():
          '''Compute the base of natural logarithms.

          >>> 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 або нижчої версії може зробити pickles Python 3.1 нечитабельними в Python 3.0. Одним із рішень є використання протоколу 3. Іншим рішенням є встановлення опції fix_imports на `False`. Дивіться обговорення вище для отримання додаткової інформації.