Что нового в 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. Более подробно см. обсуждение выше.