Что нового в Python 3.1¶
- Автор
Раймонд Хеттингер
В этой статье рассказывается о новых возможностях в Python 3.1 по сравнению с 3.0. Python 3.1 был выпущен 27 июня 2009 года.
PEP 372: Упорядоченные словари¶
Обычные словари Python перебирают пары ключ/значение в произвольном порядке. За прошедшие годы ряд авторов написали альтернативные реализации, которые помнят порядок, в котором ключи были вставлены изначально. Основываясь на опыте этих реализаций, был введен новый класс collections.OrderedDict
.
API OrderedDict практически не отличается от обычных словарей, но перебор ключей и значений осуществляется в гарантированном порядке в зависимости от того, когда ключ был вставлен первым. Если новая запись перезаписывает существующую, исходная позиция вставки остается неизменной. Удаление записи и повторная вставка переместит ее в конец.
Стандартная библиотека теперь поддерживает использование упорядоченных словарей в нескольких модулях. Модуль configparser
использует их по умолчанию. Это позволяет читать, изменять и затем записывать конфигурационные файлы в их первоначальном порядке. Метод _asdict() для модуля collections.namedtuple()
теперь возвращает упорядоченный словарь, значения которого располагаются в том же порядке, что и индексы кортежей. Модуль json
в настоящее время дополняется object_pairs_hook, чтобы позволить декодеру строить упорядоченные словари. Также была добавлена поддержка сторонних инструментов, таких как PyYAML.
См.также
- PEP 372 - Упорядоченные словари
PEP написан Армином Ронахером и Раймондом Хеттингером. Реализация написана Раймондом Хеттингером.
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).
Функция
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 - целое число. Ранее он возвращал float:>>> round(1123, -2) 1100
(Внесено Марком Дикинсоном; 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
все еще имеет место, даже если представления могут говорить об обратном.Новый алгоритм зависит от определенных функций в базовой реализации с плавающей запятой. Если требуемые возможности не найдены, будет продолжать использоваться старый алгоритм. Кроме того, протоколы text pickle обеспечивают кросс-платформенную переносимость за счет использования старого алгоритма.
(При участии Эрика Смита и Марка Дикинсона; 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()
теперь имеет необязательный аргумент шаг и может принимать любой тип счетной последовательности, включая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
для приложений, которые не используют логирование, но вызывают библиотечный код. Установка обработчика с нулевым значением позволит подавить ложные предупреждения типа «Не удалось найти обработчиков для логгера foo»:>>> h = logging.NullHandler() >>> logging.getLogger("foo").addHandler(h)
(Внесено Винаем Саджипом; bpo-4384).
Модуль
runpy
, поддерживающий переключатель командной строки-m
, теперь поддерживает выполнение пакетов путем поиска и выполнения подмодуля__main__
при указании имени пакета.(Предоставлено Andi Vajda; 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
Кроме того, было добавлено несколько новых методов утверждения, включая
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).
Модуль
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.'
Досадным, но неизбежным побочным эффектом этого изменения является то, что pickle протокола 2, созданные в Python 3.1, не будут читаться в Python 3.0. При переносе данных между реализациями Python 3.x следует использовать новейший протокол pickle, протокол 3, поскольку он не пытается сохранить совместимость с Python 2.x.
(При участии Александра Вассалотти и Антуана Питру, bpo-6137).
Был добавлен новый модуль
importlib
. Он предоставляет полную, переносимую, чистую ссылочную реализацию оператораimport
и его аналога, функции__import__()
. Это существенный шаг вперед в документировании и определении действий, происходящих во время импорта.(При участии Бретта Кэннона.)
Оптимизации¶
Добавлены значительные улучшения производительности:
Новая библиотека ввода-вывода (как определено в 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 specification, который определяется в терминах Unicode.(Внесено Бобом Ипполито и преобразовано в Py3.1 Антуаном Питру и Бенджамином Петерсоном; bpo-4136).
При распикировке теперь сохраняются имена атрибутов распикированных объектов. Это экономит память и позволяет уменьшить размер маринованных объектов.
(При участии Джейка Макгуайра и Антуана Питру; bpo-5084).
IDLE¶
В меню формата IDLE появилась опция удаления пробельных символов из исходного файла.
(Внесено Роджером Д. Серви; bpo-5150).
Изменения в API Build и C¶
Изменения в процессе сборки Python и в C API включают:
Целочисленные числа теперь хранятся внутри либо в базе
2**15
, либо в базе2**30
, база определяется во время сборки. Ранее они всегда хранились в base2**15
. Использование base2**30
дает значительный прирост производительности на 64-битных машинах, но результаты тестирования на 32-битных машинах были неоднозначными. Поэтому по умолчанию используется base2**30
на 64-битных машинах и base2**15
на 32-битных; на Unix есть новая опция configure--enable-big-digits
, которая может быть использована для отмены этого значения.Помимо повышения производительности, это изменение должно быть незаметным для конечных пользователей, за одним исключением: для целей тестирования и отладки имеется новый
sys.int_info
, который предоставляет информацию о внутреннем формате, указывая количество битов на цифру и размер в байтах типа C, используемого для хранения каждой цифры:>>> import sys >>> sys.int_info sys.int_info(bits_per_digit=30, sizeof_digit=4)
(Внесено Марком Дикинсоном; bpo-4258).
Функция
PyLong_AsUnsignedLongLong()
теперь обрабатывает отрицательный pylong, поднимаяOverflowError
вместоTypeError
.(При участии Марка Дикинсона и Лисандро Далькрина; bpo-5175).
Утратил силу
PyNumber_Int()
. Вместо этого используйтеPyNumber_Long()
.(Внесено Марком Дикинсоном; bpo-4910).
Добавлена новая функция
PyOS_string_to_double()
для замены устаревших функцийPyOS_ascii_strtod()
иPyOS_ascii_atof()
.(Внесено Марком Дикинсоном; bpo-5914).
Добавлен тип
PyCapsule
в качестве замены APIPyCObject
. Основное отличие заключается в том, что новый тип имеет четко определенный интерфейс для передачи информации о безопасности типизации и менее сложную сигнатуру для вызова деструктора. Старый тип имел проблематичный API и в настоящее время устарел.(Внесено Ларри Хастингсом; bpo-5630).
Перенос на Python 3.1¶
В этом разделе перечислены ранее описанные изменения и другие исправления, которые могут потребовать внесения изменений в ваш код:
Новые представления строк с плавающей запятой могут нарушить существующие доктесты. Например:
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 или ниже может сделать Python 3.1 pickle нечитаемым в Python 3.0. Одно из решений - использовать протокол 3. Другое решение - установить опцию fix_imports в
False
. Более подробно см. обсуждение выше.