Что нового в Python 3.1
Учимся программировать на Python
Python - один из самых востребованных языков программирования. Подпишитесь на бесплатную рассылку и получайте статьи и видео о программировании на Python. Подробнее... |
В Python 3.1 по сравнению с версией 3.0 добавлено довольно много изменений. А именно…
Упорядоченные словари
Обычные словари Python перебирают пары ключ/значение в произвольном порядке.
На протяжении многих лет ряд авторов писали альтернативные реализации, которые запоминают порядок
первоначальной вставки ключей. Основываясь на опыте этих внедрений, введен новый класс
collections.OrderedDict
.
API OrderedDict
по существу такой же, как у обычных словарей, но будет перебирать ключи и значения в гарантированном порядке в зависимости от того, когда ключ был вставлен впервые. Если новая запись перезаписывает существующую запись, исходная позиция вставки остается неизменной. Удаление записи и её повторная вставка переместят её в конец.
Стандартная библиотека теперь поддерживает использование упорядоченных словарей в нескольких модулях. Модуль
configparser
использует их по умолчанию. Это позволяет считывать, изменять и затем записывать
обратно файлы конфигурации в их первоначальном порядке. Метод _asdict()
для
collections.namedtuple()
теперь возвращает упорядоченный словарь со значениями,
отображаемыми в том же порядке, что и базовые индексы кортежей. Модуль json
создается с помощью
object_pairs_hook
, чтобы декодер мог создавать упорядоченные значения.
Также была добавлена поддержка сторонних инструментов, таких как PyYAML.
Спецификатор формата для разделения тысяч
Встроенная функция 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
.
Другие языковые изменения
Некоторые небольшие изменения, внесенные в основу языка Python, заключаются в следующем:
Каталоги и zip-архивы, содержащие файл __main__.py
теперь можно выполнить напрямую,
передав его имя интерпретатору. Каталог или zip-файл автоматически вставляется в качестве первой записи в
sys.path
.
Тип 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
Поля в строках format()
теперь можно автоматически нумеровать (раньше для строки требовались
бы пронумерованные поля, такие как 'Sir {0} of {1}'
):
>>> 'Sir {} of {}'.format('Gallahad', 'Camelot') 'Sir Gallahad of Camelot'
Функция string.maketrans()
устарела и заменена новыми статическими методами
bytes.maketrans()
и bytearray.maketrans()
. Это изменение устраняет путаницу,
связанную с тем, какие типы поддерживались модулем string
. Теперь str
,
bytes
и bytearray
имеют свои собственные методы maketrans
и
translate
с промежуточными таблицами перевода соответствующего типа.
Синтаксис оператора with
теперь позволяет использовать несколько контекстных менеджеров
в одном операторе (с новым синтаксисом функция contextlib.nested()
больше не нужна и теперь устарела):
>>> with open('mylog.txt') as infile, open('a.out', 'w') as outfile: ... for line in infile: ... if '' in line: ... outfile.write(line)
round(x, n)
теперь возвращает целое число, если x
является целым числом. Ранее он возвращал значение с плавающей запятой:
>>> round(1123, -2) 1100
Python теперь использует алгоритм Дэвида Гэя для нахождения кратчайшего представления с плавающей запятой,
которое не изменяет своего значения. Это должно помочь смягчить некоторую путаницу, связанную с двоичными
числами с плавающей запятой. Значение легко увидеть с помощью такого числа, как 1.1
, которое не имеет точного эквивалента в двоичном формате с плавающей запятой.
Поскольку точного эквивалента не существует, выражение типа float('1.1')
вычисляется до ближайшего
представимого значения, которое равно 0x1.199999999999ap+0
в шестнадцатеричном формате или
1.1000000000000088817841970012523233890533447265625
в десятичном формате. Это ближайшее значение использовалось и до сих пор используется в последующих вычислениях с плавающей запятой. Что нового, так это то, как отображается номер.
Раньше Python использовал простой подход. Значение repr(1.1)
вычислялось как
format(1.1, '.17g')
, который оценивался как '1.10000000000001'
. Преимущество
использования 17 цифр заключалось в том, что оно основывалось на правилах IEEE-754, гарантирующих, что
eval(repr(1.1))
будет возвращаться точно к своему исходному значению. Недостатком является то, что многие люди сочли вывод сбивающим с толку (ошибочно приняв внутренние ограничения двоичного представления с плавающей запятой за проблему с самим Python).
Новый алгоритм для repr(1.1)
более умный и возвращает '1.1'
. По сути, он выполняет поиск по всем эквивалентным строковым представлениям (тем, которые сохраняются с тем же базовым значением с плавающей запятой) и возвращает кратчайшее представление. Новый алгоритм, как правило, выдает более чистые представления, когда это возможно, но он не изменяет базовые значения.
Таким образом, по-прежнему имеет место тот факт, что 1.1 + 2.2 != 3.3
, хотя представления могут предполагать обратное. Новый алгоритм зависит от определенных функций базовой реализации с плавающей запятой. Если требуемые функции не будут найдены, старый алгоритм будет продолжать использоваться. Кроме того, протоколы текстовых преобразований обеспечивают кроссплатформенную переносимость с использованием старого алгоритма.
Новые, улучшенные и устаревшие модули
Добавлен класс collections.Counter
для поддержки удобного подсчета уникальных элементов в последовательности или повторяющихся:
>>> Counter(['red', 'blue', 'red', 'green', 'blue', 'blue']) Counter({'blue': 3, 'red': 2, 'green': 1})
Добавлен новый модуль tkinter.ttk
для доступа к набору виджетов на тему Tk
.
Основная идея ttk
состоит в том, чтобы отделить, насколько это возможно, код, реализующий поведение виджета, от кода, реализующего его внешний вид.
Классы gzip.GzipFile
и bz2.BZ2File
теперь поддерживают протокол управления контекстом:
>>> # Automatically close file after writing >>> with gzip.GzipFile(filename, "wb") as f: ... f.write(b"xxx")
Модуль decimal
теперь поддерживает методы создания десятичного объекта из двоичного числа с плавающей запятой. Преобразование является точным, но иногда может быть неожиданным:
>>> 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)]
Функции re.sub()
, re.subn()
и re.split()
теперь принимают параметр flags
.
Модуль logging
теперь реализует простой класс logging.NullHandler
для приложений,
которые не используют ведение журнала, но вызывают библиотечный код, который это делает. Передача
в обработчик значения null
будет подавлять ложные предупреждения, такие как “Не удалось найти обработчики для logger foo”:
>>> h = logging.NullHandler() >>> logging.getLogger("foo").addHandler(h)
Модуль runpy
, который поддерживает переключатель командной строки -m
,
теперь поддерживает выполнение пакетов путем поиска и выполнения подмодуля __main__
при указании имени пакета.
Модуль pdb
теперь может получать доступ и отображать исходный код, загруженный через
zipimport
(или любой другой соответствующий PEP 302 загрузчик).
Объекты functools.partial
теперь можно сериализовать.
Добавлены pydoc
разделов справки для символов, чтобы help('@')
работала должным образом в интерактивной среде.
Модуль 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)
Модули nntplib
и imaplib
теперь поддерживают IPv6
.
Модуль pickle
был адаптирован для лучшей совместимости с Python 2.x при использовании с протоколом 2
или ниже. Реорганизация стандартной библиотеки изменила формальную ссылку для многих объектов. Например,
__builtin__.set
в Python 2 называется buildings.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.'
Прискорбным, но неизбежным побочным эффектом этого изменения является то, что протоколы
pickle
2, созданные Python 3.1, не будут доступны для чтения с помощью Python 3.0.
Последний протокол pickle
, протокол 3, следует использовать при переносе данных между реализациями Python 3.x, поскольку он не пытается оставаться совместимым с Python 2.x.
Был добавлен новый модуль importlib
. Он предоставляет полную, переносимую, чистую эталонную
реализацию инструкции import
на языке Python и ее аналога, функции __import__()
. Это представляет собой существенный шаг вперед в документировании и определении действий, которые происходят во время импорта.
Оптимизации
Были добавлены значительные улучшения производительности:
- Новая библиотека ввода-вывода (как определено в PEP 3116) была в основном написана на Python и быстро оказалась проблемным узким местом в Python 3.0. В Python 3.1 библиотека ввода-вывода была полностью переписана на C и работает от 2 до 20 раз быстрее в зависимости от поставленной задачи. Чистая версия Python по-прежнему доступна для экспериментов с помощью модуля
_pyio
. - Добавлена эвристика, позволяющая сборщику мусора не отслеживать кортежи и словари, содержащие только неотслеживаемые объекты. Это может уменьшить размер коллекций и, следовательно, расходы ресурсов на сборку мусора в длительно работающих программах, в зависимости от их конкретного использования типов данных.
- Включение опции настройки с именем
--with-computed-gotos
в компиляторах, которые её поддерживают (в частности: gcc, SunPro, icc), цикл оценки байт-кода компилируется с помощью нового механизма диспетчеризации, который обеспечивает ускорение до 20%, в зависимости от системы, компилятора и эталона. - Декодирование UTF-8, UTF-16 и LATIN-1 теперь в два-четыре раза быстрее.
- Модуль
json
теперь имеет расширение C для существенного повышения его производительности. Кроме того, API был изменен таким образом, чтобыjson
работал только сstr
, а не сbytes
. Это изменение приводит к тому, что модуль полностью соответствует спецификации JSON, которая определена в терминах Unicode. - При удалении имена атрибутов выделенных объектов теперь интернируются. Это экономит память и позволяет сериализации быть меньше.
IDLE
Меню форматирования IDLE теперь предоставляет возможность удалять конечные пробелы из исходного файла.
Изменения в сборке С API
Изменения в процессе сборки Python и в C API включают следующее…
Целые числа теперь хранятся внутри либо в базе 2**15, либо в базе 2**30, причем база определяется во время
сборки. Раньше они всегда хранились в базе 2**15. Использование базы 2**30 обеспечивает значительное
повышение производительности на 64-разрядных машинах, но результаты тестов на 32-разрядных машинах были
неоднозначными. Следовательно, по умолчанию используется база 2**30 на 64-разрядных машинах и база 2**15 на
32-разрядных машинах. В Unix есть новая опция настройки -enable-big-digits
, которая может использоваться для переопределения этого значения по умолчанию.
Помимо повышения производительности, это изменение должно быть незаметным для конечных пользователей,
за одним исключением: для целей тестирования и отладки есть новый sys.int_info
, который предоставляет информацию о внутреннем формате, указывая количество бит на цифру и размер в байтах типа C, используемого для хранения каждой цифры:
>>> import sys >>> sys.int_info sys.int_info(bits_per_digit=30, sizeof_digit=4)
Функция PyLong_AsUnsignedLongLong()
теперь обрабатывает отрицательный pylong
, вызывая
OverflowError
вместо TypeError
.
Устарела функция PyNumber_Int()
. Вместо неё используйте PyNumber_Long()
.
Добавлена новая функция PyOS_string_to_double()
для замены устаревших функций
pyos_ascii_strtod()
и pyos_ascii_atof()
.
Добавлен PyCapsule
в качестве замены API PyCObject
. Принципиальное отличие заключается в том, что новый тип имеет четко определенный интерфейс для передачи информации о безопасности ввода и менее сложную сигнатуру для вызова деструктора. У старого типа был проблемный API, и теперь он устарел.
Перенос на Python 3.1
В этом разделе перечислены ранее описанные изменения и другие исправления, которые могут потребовать внесения изменений в ваш код.
Новые представления строк с плавающей запятой могут нарушать существующие doctests
. Например:
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
. Более подробную информацию смотрите в обсуждении выше.
Вступить в группу "Основы программирования"
Подписаться на канал в РУТУБ Подписаться на Дзен-канал Подписаться на рассылки по программированию |
Все способы изучить Python
Каждый раз, изучая какую-то новую науку, мы задаёмся вопросом - где взять обучающие материалы. Конечно, сегодня нам помогает в этом Интернет. Но иногда на поиски уходит очень много времени, а нужного результата мы не получаем... Собрал для вас кучу полезных ссылок для изучения Python. не благодарите ))) Подробнее... |