Что нового в Python 3.1¶
- Автор:
Раймонд Хеттингер
В этой статье рассказывается о новых функциях Python 3.1 по сравнению с версией 3.0. Версия Python 3.1 была выпущена 27 июня 2009 года.
PEP 372: Упорядоченные словари¶
Обычные словари Python перебирают пары ключ/значение в произвольном порядке. За прошедшие годы ряд авторов написали альтернативные реализации, которые запоминают порядок, в котором ключи были первоначально вставлены. Основываясь на опыте этих реализаций, был введен новый класс collections.OrderedDict
.
API OrderedDict практически не отличается от обычных словарей, но выполняет итерацию по ключам и значениям в гарантированном порядке в зависимости от того, когда ключ был вставлен впервые. Если новая запись перезаписывает существующую запись, исходная позиция вставки остается неизменной. Удаление записи и ее повторная вставка приведут к ее перемещению в конец.
Стандартная библиотека теперь поддерживает использование упорядоченных словарей в нескольких модулях. Модуль configparser
использует их по умолчанию. Это позволяет считывать, изменять и затем записывать обратно в исходном порядке файлы конфигурации. Метод _addict() для collections.namedtuple()
теперь возвращает ordereddictionary со значениями, расположенными в том же порядке, что и базовые индексы кортежей. Модуль json
дополняется object_pairs_hook, чтобы декодер мог создавать упорядоченные указатели. Также была добавлена поддержка сторонних инструментов, таких как PyYAML.
См.также
- PEP 372 - Упорядоченные словари
Руководство написано Армином Роначером и Рэймондом Хеттингером. Реализация написана Рэймондом Хеттингером.
Поскольку упорядоченный словарь запоминает порядок вставки, его можно использовать в сочетании с сортировкой для создания отсортированного словаря:
>>> # 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)])
Новые отсортированные словари сохраняют свой порядок сортировки при удалении записей. Но при добавлении новых ключей ключи добавляются в конец, и сортировка не поддерживается.
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 является целым числом. Ранее он возвращал значение с плавающей точкой:>>> 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'
. По сути, он выполняет поиск по всем эквивалентным строковым представлениям (тем, которые сохраняются с одним и тем же базовым значением с плавающей точкой) и возвращает кратчайшее представление.Новый алгоритм, как правило, выдает более четкие представления, когда это возможно, но не изменяет базовые значения. Таким образом, по-прежнему имеет место
1.1 + 2.2 != 3.3
, хотя представления могут свидетельствовать об обратном.Новый алгоритм зависит от некоторых особенностей базовой реализации с плавающей запятой. Если требуемые функции не найдены, будет продолжено использование старого алгоритма. Кроме того, протоколы распознавания текста обеспечивают кроссплатформенную переносимость, используя старый алгоритм.
(Авторы: Эрик Смит и Марк Дикинсон; 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
теперь поддерживает пропуск отдельных тестов или классов тестов. Также он поддерживает пометку теста как ожидаемого сбоя, т.е. теста, который, как известно, был нарушен, но не должен учитываться как сбой в результатах тестирования: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 или ниже, средство выбора будет автоматически использовать старые имена 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. При переносе данных между реализациями Python 3.x следует использовать последний протокол pickle, протокол 3, поскольку он не пытается сохранить совместимость с 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.)
При включении опции 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 теперь предоставляет возможность удалять завершающие пробелы из исходного файла.
(Автор: Роджер Д. Серви; bpo-5150.)
Изменения в сборке и C API¶
Изменения в процессе сборки Python и в C API включают:
Целые числа теперь хранятся внутри системы либо в базе
2**15
, либо в базе2**30
, причем база определяется во время сборки. Ранее они всегда хранились в базе2**15
. Использование базовой версии2**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()
теперь обрабатывает отрицательный столбец, поднимая значение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 или ниже может сделать pickles Python 3.1 нечитаемыми в Python 3.0. Одним из решений является использование протокола 3. Другое решение - установить для параметра fix_imports значение
False
. Более подробную информацию смотрите в обсуждении выше.