2.4.md
1> **Источник:** https://python-all.ru/3.13/whatsnew/2.4.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# Что нового в Python 2.489**Автор:**1011A.M. Kuchling1213В этой статье описываются новые возможности Python 2.4.1, выпущенного 30 марта, 2005.1415Python 2.4 – релиз среднего размера. Он не вносит столько изменений, как радикальный Python 2.2, но добавляет больше возможностей, чем консервативный 2.3 релиз. Наиболее значительные новые языковые возможности – это декораторы функций и выражения-генераторы; большинство остальных изменений касаются стандартной библиотеки.1617Согласно журналам изменений CVS, между Python 2.3 и 2.4 было применено 481 исправление и исправлено 502 ошибки. Обе цифры, скорее всего, занижены.1819Эта статья не ставит целью дать полную спецификацию каждой новой возможности, а вместо этого предоставляет краткое введение в каждую из них. За полными подробностями следует обращаться к документации Python 2.4, например, к справочнику по библиотеке Python и руководству по языку Python. Часто вас будут отсылать к PEP для конкретной новой возможности, где объясняются детали реализации и обоснование проекта.2021## PEP 218: Встроенные объекты множеств2223Python 2.3 представил модуль `sets`. Теперь в ядро Python добавлены реализации наборов данных на C в виде двух новых встроенных типов, `set(iterable)` и `frozenset(iterable)`. Они обеспечивают высокоскоростные операции для проверки членства, удаления дубликатов из последовательностей, и для математических операций, таких как объединение, пересечение, разность и симметрическая разность.2425```python26>>> a = set('abracadabra') # Сформировать множество из строки27>>> 'z' in a # быстрая проверка принадлежности28False29>>> a # уникальные буквы в a30set(['a', 'r', 'b', 'c', 'd'])31>>> ''.join(a) # Преобразовать обратно в строку32'arbcd'3334>>> b = set('alacazam') # Сформировать второе множество35>>> a - b # буквы, которые есть в a, но нет в b36set(['r', 'd', 'b'])37>>> a | b # Буквы из a или b38set(['a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'])39>>> a & b # буквы, которые есть и в a, и в b40set(['a', 'c'])41>>> a ^ b # буквы, которые есть в a или в b, но не в обоих42set(['r', 'd', 'b', 'm', 'z', 'l'])4344>>> a.add('z') # Добавить новый элемент45>>> a.update('wxy') # Добавить несколько новых элементов46>>> a47set(['a', 'c', 'b', 'd', 'r', 'w', 'y', 'x', 'z'])48>>> a.remove('x') # извлечь один элемент49>>> a50set(['a', 'c', 'b', 'd', 'r', 'w', 'y', 'z'])51```5253Тип [`frozenset()`](https://python-all.ru/3.13/library/stdtypes.html#frozenset) – это неизменяемая версия [`set()`](https://python-all.ru/3.13/library/stdtypes.html#set). Поскольку он неизменяем и хешируем, его можно использовать в качестве ключа словаря или элемента другого множества.5455Модуль `sets` остаётся в стандартной библиотеке и может быть полезен, если вы пожелаете создать подклассы `Set` или `ImmutableSet`. В настоящее время нет планов объявлять модуль устаревшим.5657> **См. также**58>59> **[**PEP 218**](https://python-all.ru/3.13/whatsnew/2.4.html) – Добавление встроенного типа объектов-множеств**60>61> Изначально предложено Грегом Уилсоном, окончательно реализовано Рэймондом Хеттингером.6263## PEP 237: Унификация длинных целых и целых чисел6465Долгий процесс перехода по этому PEP, начатый в Python 2.2, делает ещё один шаг вперёд в Python 2.4. В 2.3 некоторые целочисленные операции, которые вели бы себя по-разному после унификации int/long, вызывали предупреждения [`FutureWarning`](https://python-all.ru/3.13/library/exceptions.html#FutureWarning) и возвращали значения, ограниченные 32 или 64 битами (в зависимости от платформы). В 2.4 эти выражения больше не выдают предупреждение, а вместо этого возвращают другой результат, обычно длинное целое.6667Проблемные выражения – это в основном сдвиги влево и длинные шестнадцатеричные и восьмеричные константы. Например, `2 << 32` в 2.3 вызывает предупреждение, вычисляясь в 0 на 32-битных платформах. В Python 2.4 это выражение теперь возвращает правильный ответ: 8589934592.6869> **См. также**70>71> **[**PEP 237**](https://python-all.ru/3.13/whatsnew/2.4.html) – Унификация длинных целых и целых чисел**72>73> Оригинальный PEP написан Моше Задкой и GvR. Изменения для 2.4 были реализованы Калле Свенссоном.7475## PEP 289: Выражения-генераторы7677Функция итераторов, введённая в Python 2.2, и модуль [`itertools`](https://python-all.ru/3.13/library/itertools.html#module-itertools) облегчают написание программ, которые проходят по большим наборам данных без необходимости держать весь набор данных в памяти одновременно. Списковые включения не очень вписываются в эту картину, поскольку они создают объект списка Python, содержащий все элементы. Это неизбежно загружает все объекты в память, что может быть проблемой, если набор данных очень большой. При попытке написать программу в функциональном стиле естественно написать что-то вроде:7879```python80links = [link for link in get_all_links() if not link.followed]81for link in links:82 ...83```8485вместо8687```python88for link in get_all_links():89 if link.followed:90 continue91 ...92```9394Первая форма более лаконична и, возможно, более читаема, но если вы работаете с большим количеством объектов ссылок, вам придётся писать вторую форму, чтобы избежать одновременного хранения всех объектов ссылок в памяти.9596Выражения-генераторы работают аналогично списковым включениям, но не материализуют весь список; вместо этого они создают генератор, который будет возвращать элементы один за другим. Приведённый выше пример можно записать так:9798```python99links = (link for link in get_all_links() if not link.followed)100for link in links:101 ...102```103104Выражения-генераторы всегда должны быть заключены в круглые скобки, как в приведённом выше примере. Скобки, обозначающие вызов функции, тоже подходят, поэтому если вы хотите создать итератор, который будет немедленно передан функции, вы можете написать:105106```python107print sum(obj.count for obj in list_all_objects())108```109110Выражения-генераторы отличаются от списковых включений в различных мелочах. Наиболее заметно, что переменная цикла (*obj* в примере выше) недоступна за пределами выражения-генератора. Списковые включения оставляют переменную присвоенной её последнему значению; будущие версии Python изменят это, сделав списковые включения соответствующими выражениям-генераторам в этом отношении.111112> **См. также**113>114> **[**PEP 289**](https://python-all.ru/3.13/whatsnew/2.4.html) – Выражения-генераторы**115>116> Предложено Рэймондом Хеттингером, реализовано Дживоном Сео при ранних усилиях, направляемых Хе-Шиком Чаном.117118## PEP 292: Более простые подстановки в строках119120Некоторые новые классы в стандартной библиотеке предоставляют альтернативный механизм для подстановки переменных в строки; этот стиль подстановки может быть лучше для приложений, где неподготовленным пользователям нужно редактировать шаблоны.121122Обычный способ подстановки переменных по имени – оператор `%`:123124```python125>>> '%(page)i: %(title)s' % {'page':2, 'title': 'The Best of Times'}126'2: The Best of Times'127```128129При написании шаблонной строки легко забыть `i` или `s` после закрывающей скобки. Это не большая проблема, если шаблон находится в модуле Python, потому что вы запускаете код, получаете «Unsupported format character» [`ValueError`](https://python-all.ru/3.13/library/exceptions.html#ValueError) и исправляете проблему. Однако представьте приложение вроде Mailman, где шаблонные строки или переводы редактируются пользователями, которые не знакомы с языком Python. Синтаксис строки формата сложно объяснить таким пользователям, и если они допустят ошибку, сложно дать полезную обратную связь.130131PEP 292 добавляет класс `Template` в модуль [`string`](https://python-all.ru/3.13/library/string.html#module-string), который использует `$` для обозначения подстановки:132133```python134>>> import string135>>> t = string.Template('$page: $title')136>>> t.substitute({'page':2, 'title': 'The Best of Times'})137'2: The Best of Times'138```139140Если ключ отсутствует в словаре, метод `substitute()` вызовет исключение [`KeyError`](https://python-all.ru/3.13/library/exceptions.html#KeyError). Также есть метод `safe_substitute()`, который игнорирует отсутствующие ключи:141142```python143>>> t = string.Template('$page: $title')144>>> t.safe_substitute({'page':3})145'3: $title'146```147148> **См. также**149>150> **[**PEP 292**](https://python-all.ru/3.13/whatsnew/2.4.html) – Упрощённые строковые подстановки**151>152> Написано и реализовано Barry Warsaw.153154## PEP 318: Декораторы функций и методов155156Python 2.2 расширил объектную модель Python, добавив статические методы и методы класса, но не расширил синтаксис Python, чтобы предоставить новый способ определения статических методов или методов класса. Вместо этого нужно было написать инструкцию [`def`](https://python-all.ru/3.13/reference/compound_stmts.html#def) обычным способом и передать полученный метод функции [`staticmethod()`](https://python-all.ru/3.13/library/functions.html#staticmethod) или [`classmethod()`](https://python-all.ru/3.13/library/functions.html#classmethod), которая оборачивала функцию как метод нового типа. Код выглядел так:157158```python159class C:160 def meth (cls):161 ...162163 meth = classmethod(meth) # перепривязать имя к обёрнутому методу класса164```165166Если метод был очень длинным, было легко пропустить или забыть вызов [`classmethod()`](https://python-all.ru/3.13/library/functions.html#classmethod) после тела функции.167168Всегда предполагалось добавить синтаксис, чтобы сделать такие определения более читаемыми, но на момент выхода 2.2 хороший синтаксис не был очевиден. Сегодня хороший синтаксис *всё ещё* не очевиден, но пользователи просят более простого доступа к этой возможности; был добавлен новый синтаксический элемент для удовлетворения этой потребности.169170Новая возможность называется «декораторы функций». Название происходит от идеи, что [`classmethod()`](https://python-all.ru/3.13/library/functions.html#classmethod), [`staticmethod()`](https://python-all.ru/3.13/library/functions.html#staticmethod) и им подобные сохраняют дополнительную информацию в объекте функции; они *декорируют* функции дополнительными деталями.171172Обозначение заимствовано из Java и использует символ `'@'` как индикатор. С использованием нового синтаксиса приведённый выше пример был бы записан так:173174```python175class C:176177 @classmethod178 def meth (cls):179 ...180```181182`@classmethod` – это сокращённая запись для присваивания `meth=classmethod(meth)`. В более общем случае, если есть следующее:183184```python185@A186@B187@C188def f ():189 ...190```191192Это эквивалентно следующему коду без декораторов:193194```python195def f(): ...196f = A(B(C(f)))197```198199Декораторы должны находиться на строке перед определением функции, по одному декоратору на строку, и не могут быть на той же строке, что и инструкция def, то есть `@A def f(): ...` недопустимо. Можно декорировать только определения функций, либо на уровне модуля, либо внутри класса; нельзя декорировать определения классов.200201Декоратор – это просто функция, которая принимает декорируемую функцию в качестве аргумента и возвращает либо ту же функцию, либо какой-то новый объект. Возвращаемое значение декоратора не обязано быть вызываемым (хотя обычно оно вызываемое), если только к результату не будут применяться другие декораторы. Написать собственные декораторы легко. Следующий простой пример просто устанавливает атрибут у объекта функции:202203```python204>>> def deco(func):205... func.attr = 'decorated'206... return func207...208>>> @deco209... def f(): pass210...211>>> f212<function f at 0x402ef0d4>213>>> f.attr214'decorated'215>>>216```217218В качестве чуть более реалистичного примера следующий декоратор проверяет, что переданный аргумент является целым числом:219220```python221def require_int (func):222 def wrapper (arg):223 assert isinstance(arg, int)224 return func(arg)225226 return wrapper227228@require_int229def p1 (arg):230 print arg231232@require_int233def p2(arg):234 print arg*2235```236237Пример в [**PEP 318**](https://python-all.ru/3.13/whatsnew/2.4.html) содержит более продвинутую версию этой идеи, которая позволяет как указать требуемый тип, так и проверить возвращаемый тип.238239Функции-декораторы могут принимать аргументы. Если аргументы переданы, ваша функция-декоратор вызывается только с этими аргументами и должна вернуть новую функцию-декоратор; эта функция должна принимать одну функцию и возвращать функцию, как описано ранее. Другими словами, `@A @B @C(args)` превращается в:240241```python242def f(): ...243_deco = C(args)244f = A(B(_deco(f)))245```246247Правильно реализовать это может быть немного запутанно, но не слишком сложно.248249Небольшое связанное изменение делает атрибут [`func_name`](https://python-all.ru/3.13/reference/datamodel.html#function.__name__) функций доступным для записи. Этот атрибут используется для отображения имён функций в трассировках, поэтому декораторы должны изменять имя любой новой функции, которая создаётся и возвращается.250251> **См. также**252>253> **[**PEP 318**](https://python-all.ru/3.13/whatsnew/2.4.html) – Декораторы функций, методов и классов**254>255> Авторы: Kevin D. Smith, Jim Jewett и Skip Montanaro. Несколько человек написали патчи, реализующие декораторы функций, но тот, который был фактически включён, – патч #979728, написанный Mark Russell.256>257> **[https://wiki.python.org/moin/PythonDecoratorLibrary](https://python-all.ru/3.13/whatsnew/2.4.html)**258>259> Эта вики-страница содержит несколько примеров декораторов.260261## PEP 322: Обратная итерация262263Новая встроенная функция `reversed(seq)` принимает последовательность и возвращает итератор, который перебирает элементы последовательности в обратном порядке.264265```python266>>> for i in reversed(xrange(1,4)):267... print i268...269327022711272```273274По сравнению с расширенной срезкой, например `range(1,4)[::-1]`, [`reversed()`](https://python-all.ru/3.13/library/functions.html#reversed) легче читается, работает быстрее и использует значительно меньше памяти.275276Обратите внимание, что [`reversed()`](https://python-all.ru/3.13/library/functions.html#reversed) принимает только последовательности, а не произвольные итераторы. Если нужно обратить итератор, сначала преобразуйте его в список с помощью [`list()`](https://python-all.ru/3.13/library/stdtypes.html#list).277278```python279>>> input = open('/etc/passwd', 'r')280>>> for line in reversed(list(input)):281... print line282...283root:*:0:0:System Administrator:/var/root:/bin/tcsh284 ...285```286287> **См. также**288>289> **[**PEP 322**](https://python-all.ru/3.13/whatsnew/2.4.html) – Обратная итерация**290>291> Написано и реализовано Raymond Hettinger.292293## PEP 324: Новый модуль подпроцесс294295Стандартная библиотека предоставляет несколько способов выполнения подпроцесса, предлагая разные возможности и разный уровень сложности. `os.system(command)` прост в использовании, но медленный (он запускает процесс оболочки, который выполняет команду) и опасен (нужно быть осторожным с экранированием метасимволов оболочки). Модуль `popen2` предлагает классы, которые могут захватывать стандартный вывод и стандартную ошибку подпроцесса, но названия сбивают с толку. Модуль [`subprocess`](https://python-all.ru/3.13/library/subprocess.html#module-subprocess) исправляет это, предоставляя единый интерфейс, который содержит все необходимые возможности.296297Вместо набора классов `popen2`, [`subprocess`](https://python-all.ru/3.13/library/subprocess.html#module-subprocess) содержит единственный класс [`subprocess.Popen`](https://python-all.ru/3.13/library/subprocess.html#subprocess.Popen), конструктор которого поддерживает множество различных именованных аргументов.298299```python300class Popen(args, bufsize=0, executable=None,301 stdin=None, stdout=None, stderr=None,302 preexec_fn=None, close_fds=False, shell=False,303 cwd=None, env=None, universal_newlines=False,304 startupinfo=None, creationflags=0):305```306307*args* обычно представляет собой последовательность строк, которые будут аргументами программы, выполняемой как подпроцесс. (Если аргумент *shell* равен true, *args* может быть строкой, которая затем передаётся оболочке для интерпретации, как и в [`os.system()`](https://python-all.ru/3.13/library/os.html#os.system).)308309*stdin*, *stdout* и *stderr* определяют, какими будут потоки ввода, вывода и ошибок подпроцесса. Можно передать файловый объект или файловый дескриптор, либо использовать константу `subprocess.PIPE` для создания канала между подпроцессом и родительским процессом.310311Конструктор имеет ряд удобных опций:312313- *close\_fds* требует, чтобы все файловые дескрипторы были закрыты перед запуском подпроцесса.314- *cwd* указывает рабочий каталог, в котором будет выполняться подпроцесс (по умолчанию используется рабочий каталог родительского процесса).315- *env* – это словарь, задающий переменные окружения.316- *preexec\_fn* – это функция, которая вызывается перед запуском дочернего процесса.317- *universal\_newlines* открывает ввод и вывод дочернего процесса с использованием механизма [универсальных символов новой строки](https://python-all.ru/3.13/glossary.html#term-universal-newlines) Python.318319После создания экземпляра `Popen` можно вызвать его метод `wait()` для ожидания завершения подпроцесса, `poll()` для проверки, завершился ли он без ожидания, или `communicate(data)` для отправки строки *data* на стандартный ввод подпроцесса. `communicate(data)` затем читает любые данные, отправленные подпроцессом на стандартный вывод или стандартную ошибку, и возвращает кортеж `(stdout_data, stderr_data)`.320321`call()` – это сокращение, которое передаёт свои аргументы конструктору `Popen`, ожидает завершения команды и возвращает код состояния подпроцесса. Он может служить более безопасным аналогом [`os.system()`](https://python-all.ru/3.13/library/os.html#os.system):322323```python324sts = subprocess.call(['dpkg', '-i', '/tmp/new-package.deb'])325if sts == 0:326 # Успех327 ...328else:329 # dpkg вернул ошибку330 ...331```332333Команда вызывается без использования оболочки. Если действительно нужно использовать оболочку, можно добавить `shell=True` в качестве именованного аргумента и передать строку вместо последовательности:334335```python336sts = subprocess.call('dpkg -i /tmp/new-package.deb', shell=True)337```338339В PEP приведены различные примеры кода на shell и Python и показано, как их можно перевести в код Python, использующий [`subprocess`](https://python-all.ru/3.13/library/subprocess.html#module-subprocess). Настоятельно рекомендуется прочитать этот раздел PEP.340341> **См. также**342>343> **[**PEP 324**](https://python-all.ru/3.13/whatsnew/2.4.html) - подпроцесс - новый модуль для работы с процессами**344>345> Написан и реализован Питером Острандом (Peter Åstrand) при содействии Фредрика Лунда (Fredrik Lundh) и других.346347## PEP 327: тип данных Decimal348349Python всегда поддерживал числа с плавающей точкой (FP) как тип данных, основанный на базовом типе C double. Однако, хотя большинство языков программирования предоставляют тип с плавающей точкой, многие люди (даже программисты) не знают, что числа с плавающей точкой не могут точно представлять некоторые десятичные дроби. Новый тип `Decimal` может точно представлять эти дроби с заданной пользователем точностью.350351### Зачем нужен Decimal?352353Ограничения возникают из-за представления, используемого для чисел с плавающей точкой. Числа с плавающей точкой состоят из трёх компонентов:354355- Знак, который может быть положительным или отрицательным.356- Мантисса, которая представляет собой однозначное двоичное число, за которым следует дробная часть. Например, `1.01` в двоичной записи – это `1 + 0/2 + 1/4`, или 1.25 в десятичной записи.357- Экспонента, которая указывает, где находится десятичная точка в представляемом числе.358359Например, число 1.25 имеет положительный знак, мантиссу 1.01 (в двоичной системе) и экспоненту 0 (десятичную точку сдвигать не нужно). Число 5 имеет те же знак и мантиссу, но экспонента равна 2, потому что мантисса умножается на 4 (2 в степени экспоненты 2); 1.25 \* 4 = 5.360361Современные системы обычно поддерживают числа с плавающей точкой, соответствующие стандарту IEEE 754. Тип C double обычно реализуется как 64-битное число IEEE 754, в котором 52 бита отведено под мантиссу. Это означает, что числа могут быть заданы только с точностью 52 бита. Если нужно представить числа с бесконечно повторяющимся разложением, разложение обрезается после 52 бит. К сожалению, большинству программного обеспечения требуется вывод в десятичной системе, а обычные десятичные дроби часто являются бесконечными дробями в двоичной системе. Например, десятичное 1.1 в двоичной системе – это `1.0001100110011 ...`; 0.1 = 1/16 + 1/32 + 1/256 плюс бесконечное число дополнительных членов. IEEE 754 вынужден обрезать эту бесконечно повторяющуюся дробь после 52 разрядов, поэтому представление оказывается слегка неточным.362363Иногда эту неточность можно увидеть при выводе числа:364365```python366>>> 1.13671.1000000000000001368```369370Неточность не всегда видна при выводе числа, потому что преобразование из FP в строку десятичного числа выполняется библиотекой C, и большинство библиотек C стараются дать разумный результат. Однако, даже если она не отображается, неточность всё равно существует, и последующие операции могут увеличить ошибку.371372Для многих приложений это не имеет значения. Если я строю график точек и отображаю их на мониторе, разница между 1.1 и 1.1000000000000001 слишком мала, чтобы быть заметной. Отчёты часто ограничивают вывод определённым количеством десятичных знаков, и если округлить число до двух, трёх или даже восьми знаков, ошибка никогда не проявляется. Однако для приложений, где это важно, реализация собственных арифметических процедур требует больших усилий.373374Поэтому был создан тип `Decimal`.375376### Тип `Decimal`377378В стандартную библиотеку Python был добавлен новый модуль [`decimal`](https://python-all.ru/3.13/library/decimal.html#module-decimal). Он содержит два класса: `Decimal` и `Context`. Экземпляры `Decimal` представляют числа, а экземпляры `Context` используются для инкапсуляции различных настроек, таких как точность и режим округления по умолчанию.379380Экземпляры `Decimal` неизменяемы, как обычные целые числа и числа с плавающей точкой в Python; после создания экземпляра нельзя изменить значение, которое он представляет. Экземпляры `Decimal` можно создавать из целых чисел или строк:381382```python383>>> import decimal384>>> decimal.Decimal(1972)385Decimal("1972")386>>> decimal.Decimal("1.1")387Decimal("1.1")388```389390Также можно передавать кортежи, содержащие знак, мантиссу, представленную в виде кортежа десятичных цифр, и экспоненту:391392```python393>>> decimal.Decimal((1, (1, 4, 7, 5), -2))394Decimal("-14.75")395```396397Предостережение: бит знака – это логическое значение, поэтому 0 означает положительное число, а 1 – отрицательное.398399Преобразование из чисел с плавающей запятой создаёт небольшую проблему: должно ли число с плавающей запятой, представляющее 1.1, превратиться в десятичное число для точного 1.1 или для 1.1 плюс всевозможные неточности, которые вносятся? Было решено обойти этот вопрос и не включать такое преобразование в API. Вместо этого следует преобразовать число с плавающей запятой в строку с нужной точностью и передать строку конструктору `Decimal`:400401```python402>>> f = 1.1403>>> decimal.Decimal(str(f))404Decimal("1.1")405>>> decimal.Decimal('%.12f' % f)406Decimal("1.100000000000")407```408409Получив экземпляры `Decimal`, можно выполнять над ними обычные математические операции. Одно ограничение: возведение в степень требует целочисленного показателя:410411```python412>>> a = decimal.Decimal('35.72')413>>> b = decimal.Decimal('1.73')414>>> a+b415Decimal("37.45")416>>> a-b417Decimal("33.99")418>>> a*b419Decimal("61.7956")420>>> a/b421Decimal("20.64739884393063583815028902")422>>> a ** 2423Decimal("1275.9184")424>>> a**b425Traceback (most recent call last):426 ...427decimal.InvalidOperation: x ** (non-integer)428```429430Экземпляры `Decimal` можно сочетать с целыми числами, но не с числами с плавающей запятой:431432```python433>>> a + 4434Decimal("39.72")435>>> a + 4.5436Traceback (most recent call last):437 ...438TypeError: You can interact Decimal only with int, long or Decimal data types.439>>>440```441442Числа `Decimal` можно использовать с модулями [`math`](https://python-all.ru/3.13/library/math.html#module-math) и [`cmath`](https://python-all.ru/3.13/library/cmath.html#module-cmath), но учтите, что они будут немедленно преобразованы в числа с плавающей запятой до выполнения операции, что может привести к потере точности и правильности. Также будет возвращено обычное число с плавающей запятой, а не `Decimal`.443444```python445>>> import math, cmath446>>> d = decimal.Decimal('123456789012.345')447>>> math.sqrt(d)448351364.18288201344449>>> cmath.sqrt(-d)450351364.18288201344j451```452453Экземпляры `Decimal` имеют метод `sqrt()`, который возвращает `Decimal`, но если нужны другие вещи, например, тригонометрические функции, их придётся реализовать самостоятельно.454455```python456>>> d.sqrt()457Decimal("351364.1828820134592177245001")458```459460### Тип `Context`461462Экземпляры класса `Context` инкапсулируют несколько настроек для операций с десятичными числами:463464- `prec` – это точность, количество знаков после запятой.465- `rounding` задаёт режим округления. В модуле [`decimal`](https://python-all.ru/3.13/library/decimal.html#module-decimal) есть константы для различных вариантов: `ROUND_DOWN`, `ROUND_CEILING`, `ROUND_HALF_EVEN` и другие.466- `traps` – это словарь, определяющий, что происходит при возникновении определённых ошибок: либо возбуждается исключение, либо возвращается значение. Некоторые примеры ошибочных ситуаций: деление на ноль, потеря точности и переполнение.467468Существует контекст по умолчанию, локальный для потока, доступный при вызове `getcontext()`; можно изменить свойства этого контекста, чтобы изменить точность по умолчанию, округление или обработку исключений. Следующий пример показывает эффект изменения точности контекста по умолчанию:469470```python471>>> decimal.getcontext().prec47228473>>> decimal.Decimal(1) / decimal.Decimal(7)474Decimal("0.1428571428571428571428571429")475>>> decimal.getcontext().prec = 9476>>> decimal.Decimal(1) / decimal.Decimal(7)477Decimal("0.142857143")478```479480Действие по умолчанию для ошибочных ситуаций выбирается; модуль может либо вернуть специальное значение, например, бесконечность или не-число, либо возбудить исключение:481482```python483>>> decimal.Decimal(1) / decimal.Decimal(0)484Traceback (most recent call last):485 ...486decimal.DivisionByZero: x / 0487>>> decimal.getcontext().traps[decimal.DivisionByZero] = False488>>> decimal.Decimal(1) / decimal.Decimal(0)489Decimal("Infinity")490>>>491```492493Экземпляр `Context` также имеет различные методы форматирования чисел, такие как `to_eng_string()` и `to_sci_string()`.494495Для получения дополнительной информации обратитесь к документации модуля [`decimal`](https://python-all.ru/3.13/library/decimal.html#module-decimal), которая включает краткое руководство и справочник.496497> **См. также**498>499> **[**PEP 327**](https://python-all.ru/3.13/whatsnew/2.4.html) – Десятичный тип данных**500>501> Автор: Facundo Batista, реализовано Facundo Batista, Eric Price, Raymond Hettinger, Aahz и Tim Peters.502>503> **[http://www.lahey.com/float.htm](https://python-all.ru/3.13/whatsnew/2.4.html)**504>505> В статье используется код на Fortran для иллюстрации многих проблем, которые может вызвать неточность чисел с плавающей запятой.506>507> **[https://speleotrove.com/decimal/](https://python-all.ru/3.13/whatsnew/2.4.html)**508>509> Описание представления на основе десятичной системы. Это представление предлагается в качестве стандарта и лежит в основе нового десятичного типа Python. Большая часть этого материала была написана Mike Cowlishaw, разработчиком языка Rexx.510511## PEP 328: Многострочные импорты512513Одно из изменений языка – небольшое синтаксическое усовершенствование, направленное на упрощение импорта нескольких имён из модуля. В инструкции `from module import names` *имена* представляют собой последовательность имён, разделённых запятыми. Если последовательность очень длинная, можно либо написать несколько инструкций импорта из одного модуля, либо использовать обратную косую черту для переноса строк, например:514515```python516from SimpleXMLRPCServer import SimpleXMLRPCServer,\517 SimpleXMLRPCRequestHandler,\518 CGIXMLRPCRequestHandler,\519 resolve_dotted_attribute520```521522Синтаксическое изменение в Python 2.4 просто позволяет помещать имена в круглые скобки. Python игнорирует переводы строк внутри выражений в скобках, поэтому обратная косая черта больше не нужна:523524```python525from SimpleXMLRPCServer import (SimpleXMLRPCServer,526 SimpleXMLRPCRequestHandler,527 CGIXMLRPCRequestHandler,528 resolve_dotted_attribute)529```530531PEP также предлагает, чтобы все инструкции [`import`](https://python-all.ru/3.13/reference/simple_stmts.html#import) были абсолютными импортами, с ведущим символом `.` для указания относительного импорта. Эта часть PEP не была реализована в Python 2.4, но была завершена в Python 2.5.532533> **См. также**534>535> **[**PEP 328**](https://python-all.ru/3.13/whatsnew/2.4.html) – Импорт: многострочный и абсолютный/относительный**536>537> Автор: Aahz. Многострочные импорты реализованы Dima Dorfman.538539## PEP 331: Преобразования чисел с плавающей запятой/строк, не зависящие от локали540541Модуль [`locale`](https://python-all.ru/3.13/library/locale.html#module-locale) позволяет программам на Python выбирать различные преобразования и соглашения отображения, локализованные для определённой страны или языка. Однако модуль старался не изменять числовую локаль, поскольку различные функции в реализации Python требовали, чтобы числовая локаль оставалась установленной на локаль `'C'`. Часто это было связано с использованием C-функции `atof()`.542543Однако отказ от установки числовой локали вызывал проблемы для расширений, использующих сторонние C-библиотеки, поскольку у них не была установлена правильная локаль. Мотивирующим примером была GTK+, виджеты пользовательского интерфейса которой не отображали числа в текущей локали.544545Решение, описанное в PEP, заключается в добавлении в Python API трёх новых функций, которые выполняют преобразования только в ASCII, игнорируя настройки локали:546547- `PyOS_ascii_strtod(str, ptr)` и `PyOS_ascii_atof(str, ptr)` обе преобразуют строку в C double.548- `PyOS_ascii_formatd(buffer, buf_len, format, d)` преобразует double в строку ASCII.549550Код этих функций взят из библиотеки GLib ([https://developer-old.gnome.org/glib/2.26/](https://python-all.ru/3.13/whatsnew/2.4.html)), разработчики которой любезно перелицензировали соответствующие функции и передали их Python Software Foundation. Модуль [`locale`](https://python-all.ru/3.13/library/locale.html#module-locale) теперь может изменять числовую локаль, что позволяет расширениям, таким как GTK+, давать правильные результаты.551552> **См. также**553>554> **[**PEP 331**](https://python-all.ru/3.13/whatsnew/2.4.html) – Преобразования чисел с плавающей запятой/строк, не зависящие от локали**555>556> Автор – Christian R. Reis, реализация – Gustavo Carneiro.557558## Прочие изменения языка559560Ниже перечислены все изменения, которые Python 2.4 вносит в ядро языка Python.561562- Добавлены декораторы для функций и методов ([**PEP 318**](https://python-all.ru/3.13/whatsnew/2.4.html)).563- Добавлены встроенные типы [`set()`](https://python-all.ru/3.13/library/stdtypes.html#set) и [`frozenset()`](https://python-all.ru/3.13/library/stdtypes.html#frozenset) ([**PEP 218**](https://python-all.ru/3.13/whatsnew/2.4.html)). Среди других новых встроенных функций – функция `reversed(seq)` ([**PEP 322**](https://python-all.ru/3.13/whatsnew/2.4.html)).564- Добавлены генераторные выражения ([**PEP 289**](https://python-all.ru/3.13/whatsnew/2.4.html)).565- Некоторые числовые выражения больше не возвращают значения, ограниченные 32 или 64 битами ([**PEP 237**](https://python-all.ru/3.13/whatsnew/2.4.html)).566- Теперь можно заключать список имён в операторе `from module import names` в круглые скобки ([**PEP 328**](https://python-all.ru/3.13/whatsnew/2.4.html)).567- Метод [`dict.update()`](https://python-all.ru/3.13/library/stdtypes.html#dict.update) теперь принимает те же формы аргументов, что и конструктор [`dict`](https://python-all.ru/3.13/library/stdtypes.html#dict). Сюда входят любое отображение, любой итерируемый объект с парами ключ/значение и именованные аргументы. (Предложено Raymond Hettinger.)568- Строковые методы `ljust()`, `rjust()` и `center()` теперь принимают необязательный аргумент для указания символа заполнения, отличного от пробела. (Предложено Raymond Hettinger.)569- Строки также обзавелись методом `rsplit()`, который работает как метод `split()`, но разбивает строку с конца. (Предложено Sean Reifschneider.)570571 ```python572 >>> 'www.python.org'.split('.', 1)573 ['www', 'python.org']574 'www.python.org'.rsplit('.', 1)575 ['www.python', 'org']576 ```577- Три именованных параметра – *cmp*, *key* и *reverse* – были добавлены к методу `sort()` списков. Эти параметры упрощают некоторые распространённые случаи использования `sort()`. Все эти параметры являются необязательными.578579 Для параметра *cmp* значением должна быть функция сравнения, которая принимает два параметра и возвращает -1, 0 или +1 в зависимости от результата сравнения. Затем эта функция будет использоваться для сортировки списка. Ранее это был единственный параметр, который можно было передать в `sort()`.580581 *key* должна быть функцией с одним параметром, которая принимает элемент списка и возвращает ключ сравнения для этого элемента. Затем список сортируется с использованием ключей сравнения. Следующий пример сортирует список без учёта регистра:582583 ```python584 >>> L = ['A', 'b', 'c', 'D']585 >>> L.sort() # сортировка с учётом регистра586 >>> L587 ['A', 'D', 'b', 'c']588 >>> # использование параметра 'key' для сортировки списка589 >>> L.sort(key=lambda x: x.lower())590 >>> L591 ['A', 'b', 'c', 'D']592 >>> # старый способ593 >>> L.sort(cmp=lambda x,y: cmp(x.lower(), y.lower()))594 >>> L595 ['A', 'b', 'c', 'D']596 ```597598 Последний пример, использующий параметр *cmp*, – это старый способ выполнения сортировки без учёта регистра. Он работает, но медленнее, чем использование параметра *key*. Использование *key* вызывает метод `lower()` один раз для каждого элемента списка, в то время как использование *cmp* вызывает его дважды для каждого сравнения, поэтому использование *key* экономит вызовы метода `lower()`.599600 Для простых ключевых функций и функций сравнения часто можно избежать выражения [`lambda`](https://python-all.ru/3.13/reference/expressions.html#lambda), используя вместо этого несвязанный метод. Например, приведённую выше сортировку без учёта регистра лучше всего записать так:601602 ```python603 >>> L.sort(key=str.lower)604 >>> L605 ['A', 'b', 'c', 'D']606 ```607608 Наконец, параметр *reverse* принимает логическое значение. Если значение истинно, список будет отсортирован в обратном порядке. Вместо `L.sort(); L.reverse()` теперь можно написать `L.sort(reverse=True)`.609610 Теперь гарантируется, что результаты сортировки устойчивы. Это означает, что две записи с равными ключами будут возвращены в том же порядке, в котором они поступили на вход. Например, можно отсортировать список людей по имени, а затем отсортировать список по возрасту, в результате получится список, отсортированный по возрасту, где люди с одинаковым возрастом находятся в порядке, отсортированном по имени.611612 (Все изменения в `sort()` предложены Raymond Hettinger.)613- Появилась новая встроенная функция `sorted(iterable)`, которая работает как метод [`list.sort()`](https://python-all.ru/3.13/library/stdtypes.html#list.sort), изменяющий объект на месте, но может использоваться в выражениях. Отличия:614- входными данными может быть любой итерируемый объект;615- сортируется новосозданная копия, оригинал остаётся нетронутым; и616- выражение возвращает новую отсортированную копию617618 ```python619 >>> L = [9,7,8,3,2,4,1,6,5]620 >>> [10+i for i in sorted(L)] # можно использовать в списковом включении621 [11, 12, 13, 14, 15, 16, 17, 18, 19]622 >>> L # оригинал остаётся неизменным623 [9,7,8,3,2,4,1,6,5]624 >>> sorted('Monty Python') # любой итерируемый объект может быть входным625 [' ', 'M', 'P', 'h', 'n', 'n', 'o', 'o', 't', 't', 'y', 'y']626627 >>> # вывести содержимое словаря, отсортированное по ключам628 >>> colormap = dict(red=1, blue=2, green=3, black=4, yellow=5)629 >>> for k, v in sorted(colormap.iteritems()):630 ... print k, v631 ...632 black 4633 blue 2634 green 3635 red 1636 yellow 5637 ```638639 (Автор: Raymond Hettinger.)640- Целочисленные операции больше не будут вызывать `OverflowWarning`. Предупреждение `OverflowWarning` исчезнет в Python 2.5.641- Интерпретатор получил новый флаг [`-m`](https://python-all.ru/3.13/using/cmdline.html#cmdoption-m), который принимает имя, ищет соответствующий модуль в `sys.path` и запускает модуль как сценарий. Например, теперь можно запустить профилировщик Python с помощью `python -m profile`. (Предложено Nick Coghlan.)642- Функции `eval(expr, globals, locals)` и `execfile(filename, globals, locals)`, а также оператор `exec` теперь принимают любой тип отображения для параметра *locals*. Ранее это должен был быть обычный словарь Python. (Предложено Raymond Hettinger.)643- Встроенная функция [`zip()`](https://python-all.ru/3.13/library/functions.html#zip) и `itertools.izip()` теперь возвращают пустой список, если вызваны без аргументов. Ранее они вызывали исключение [`TypeError`](https://python-all.ru/3.13/library/exceptions.html#TypeError). Это делает их более подходящими для использования со списками аргументов переменной длины:644645 ```python646 >>> def transpose(array):647 ... return zip(*array)648 ...649 >>> transpose([(1,2,3), (4,5,6)])650 [(1, 4), (2, 5), (3, 6)]651 >>> transpose([])652 []653 ```654655 (Автор: Raymond Hettinger.)656- Сбой при импорте модуля больше не оставляет частично инициализированный объект модуля в `sys.modules`. Оставленный неполный объект модуля мог ввести в заблуждение последующие импорты того же модуля, заставляя их считаться успешными, что приводило к запутанным ошибкам. (Исправлено Tim Peters.)657- [`None`](https://python-all.ru/3.13/library/constants.html#None) теперь является константой; код, который присваивает новое значение имени `None`, теперь вызывает синтаксическую ошибку. (Автор: Raymond Hettinger.)658659### Оптимизации660661- Внутренние циклы для срезов списков и кортежей были оптимизированы и теперь работают примерно на треть быстрее. Внутренние циклы для словарей также были оптимизированы, что привело к повышению производительности для `keys()`, `values()`, `items()`, `iterkeys()`, `itervalues()` и `iteritems()`. (Автор: Raymond Hettinger.)662- Механизмы увеличения и уменьшения списков были оптимизированы по скорости и эффективности использования памяти. Добавление и извлечение элементов из списков теперь выполняется быстрее благодаря более эффективным путям кода и менее частому использованию системных `realloc()`. Также выигрывают списковые включения. [`list.extend()`](https://python-all.ru/3.13/library/stdtypes.html#list.extend) была также оптимизирована и больше не преобразует свой аргумент во временный список перед extending базового списка. (Автор: Raymond Hettinger.)663- [`list()`](https://python-all.ru/3.13/library/stdtypes.html#list), [`tuple()`](https://python-all.ru/3.13/library/stdtypes.html#tuple), [`map()`](https://python-all.ru/3.13/library/functions.html#map), [`filter()`](https://python-all.ru/3.13/library/functions.html#filter) и [`zip()`](https://python-all.ru/3.13/library/functions.html#zip) теперь работают в несколько раз быстрее с аргументами, не являющимися последовательностями, которые предоставляют метод `__len__()`. (Автор: Raymond Hettinger.)664- Методы `list.__getitem__()`, `dict.__getitem__()` и `dict.__contains__()` теперь реализованы как объекты `method_descriptor`, а не как объекты `wrapper_descriptor`. Такая форма доступа удваивает их производительность и делает их более подходящими для использования в качестве аргументов функций: `map(mydict.__getitem__, keylist)`. (Автор: Raymond Hettinger.)665- Добавлен новый опкод `LIST_APPEND`, который упрощает генерируемый байткод для списковых включений и ускоряет их примерно на треть. (Автор: Raymond Hettinger.)666- Оптимизатор байткода на маленьких окнах (peephole) был улучшен для создания более короткого и быстрого байткода; примечательно, что результирующий байткод стал более читаемым. (Улучшено Raymond Hettinger.)667- Конкатенация строк в выражениях вида `s = s + "abc"` и `s += "abc"` теперь выполняется более эффективно в определённых случаях. Эта оптимизация не будет присутствовать в других реализациях Python, таких как Jython, поэтому не следует на неё полагаться; по-прежнему рекомендуется использовать метод строк `join()`, когда нужно эффективно склеить большое количество строк. (Автор: Armin Rigo.)668669Итог оптимизаций в версии 2.4: Python 2.4 выполняет тест pystone примерно на 5% быстрее, чем Python 2.3, и на 35% быстрее, чем Python 2.2. (pystone – не самый удачный тест, но это наиболее распространённое измерение производительности Python. Ваши собственные приложения могут получить от Python 2.4 больший или меньший прирост.)670671## Новые, улучшенные и устаревшие модули672673Как обычно, стандартная библиотека Python получила ряд улучшений и исправлений ошибок. Вот частичный список наиболее заметных изменений, отсортированный по модулям в алфавитном порядке. Полный список изменений можно найти в файле `Misc/NEWS` в дереве исходного кода или просмотрев журналы CVS.674675- Функция `loop()` модуля `asyncore` теперь имеет параметр *count*, который позволяет выполнить ограниченное количество проходов по циклу опроса. По умолчанию цикл по-прежнему выполняется бесконечно.676- Модуль [`base64`](https://python-all.ru/3.13/library/base64.html#module-base64) теперь имеет более полную поддержку [**RFC 3548**](https://python-all.ru/3.13/whatsnew/2.4.html) для кодирования и декодирования Base64, Base32 и Base16, включая опциональное преобразование регистра и опциональные альтернативные алфавиты. (Автор: Barry Warsaw.)677- Модуль [`bisect`](https://python-all.ru/3.13/library/bisect.html#module-bisect) теперь имеет базовую реализацию на C для улучшения производительности. (Автор: Dmitry Vasiliev.)678- Коллекции восточноазиатских кодеков CJKCodecs, поддерживаемые Hye-Shik Chang, были интегрированы в версию 2.4. Новые кодировки:679- Китай (КНР): gb2312, gbk, gb18030, big5hkscs, hz680- Китай (Тайвань): big5, cp950681- **Японский: cp932, euc-jis-2004, euc-jp, euc-jisx0213, iso-2022-jp,**682683 iso-2022-jp-1, iso-2022-jp-2, iso-2022-jp-3, iso-2022-jp-ext, iso-2022-jp-2004, shift-jis, shift-jisx0213, shift-jis-2004684- Корейский: cp949, euc-kr, johab, iso-2022-kr685- Были добавлены некоторые другие новые кодировки: HP Roman8, ISO\_8859-11, ISO\_8859-16, PCTP-154 и TIS-620.686- Кодеки UTF-8 и UTF-16 теперь лучше справляются с получением частичных входных данных. Раньше класс `StreamReader` пытался прочитать больше данных, что делало невозможным возобновление декодирования из потока. Теперь метод `read()` будет возвращать столько данных, сколько возможно, и последующие вызовы продолжат декодирование с того места, где остановились предыдущие. (Реализовано Walter Dörwald.)687- Появился новый модуль [`collections`](https://python-all.ru/3.13/library/collections.html#module-collections) для различных специализированных типов коллекций. В настоящее время он содержит только один тип – `deque`, двустороннюю очередь, которая поддерживает эффективное добавление и удаление элементов с любого конца:688689 ```python690 >>> from collections import deque691 >>> d = deque('ghi') # создать новый deque с тремя элементами692 >>> d.append('j') # добавить новый элемент справа693 >>> d.appendleft('f') # добавить новый элемент слева694 >>> d # показать представление deque695 deque(['f', 'g', 'h', 'i', 'j'])696 >>> d.pop() # вернуть и удалить правый элемент697 'j'698 >>> d.popleft() # вернуть и удалить левый элемент699 'f'700 >>> list(d) # вывести содержимое deque701 ['g', 'h', 'i']702 >>> 'h' in d # поиск в deque703 True704 ```705706 Некоторые модули, такие как `Queue` и [`threading`](https://python-all.ru/3.13/library/threading.html#module-threading), теперь используют [`collections.deque`](https://python-all.ru/3.13/library/collections.html#collections.deque) для повышения производительности. (Автор: Raymond Hettinger.)707- Классы [`ConfigParser`](https://python-all.ru/3.13/library/configparser.html#module-configparser) были немного улучшены. Метод [`read()`](https://python-all.ru/3.13/library/configparser.html#configparser.ConfigParser.read) теперь возвращает список файлов, которые были успешно разобраны, а метод [`set()`](https://python-all.ru/3.13/library/configparser.html#configparser.ConfigParser.set) вызывает исключение [`TypeError`](https://python-all.ru/3.13/library/exceptions.html#TypeError), если ему передан аргумент *value*, не являющийся строкой. (Авторы: John Belmonte и David Goodger.)708- Модуль [`curses`](https://python-all.ru/3.13/library/curses.html#module-curses) теперь поддерживает расширение ncurses `use_default_colors()`. На платформах, где терминал поддерживает прозрачность, это позволяет использовать прозрачный фон. (Автор: Jörg Lehmann.)709- Модуль [`difflib`](https://python-all.ru/3.13/library/difflib.html#module-difflib) теперь включает класс `HtmlDiff`, который создаёт HTML-таблицу с построчным сравнением двух версий текста. (Автор: Dan Gass.)710- Пакет [`email`](https://python-all.ru/3.13/library/email.html#module-email) был обновлён до версии 3.0, в которой удалены различные устаревшие API и прекращена поддержка версий Python ниже 2.3. Версия 3.0 пакета использует новый инкрементальный парсер MIME-сообщений, доступный в модуле `email.FeedParser`. Новый парсер не требует чтения всего сообщения в память и не вызывает исключений, если сообщение имеет некорректный формат; вместо этого он записывает любые проблемы в атрибут `defect` сообщения. (Разработан Anthony Baxter, Barry Warsaw, Thomas Wouters и другими.)711- Модуль [`heapq`](https://python-all.ru/3.13/library/heapq.html#module-heapq) был переписан на C. Десятикратное повышение скорости делает модуль пригодным для обработки больших объёмов данных. Кроме того, в модуле появились две новые функции `nlargest()` и `nsmallest()`, которые используют кучи для поиска N наибольших или наименьших значений в наборе данных без затрат на полную сортировку. (Автор: Raymond Hettinger.)712- Модуль [`httplib`](https://python-all.ru/3.13/library/http.html#module-http) теперь содержит константы для кодов состояния HTTP, определённых в различных RFC, связанных с HTTP. Константы имеют имена, такие как `OK`, `CREATED`, `CONTINUE` и `MOVED_PERMANENTLY`; для получения полного списка используйте pydoc. (Автор: Andrew Eland.)713- Модуль [`imaplib`](https://python-all.ru/3.13/library/imaplib.html#module-imaplib) теперь поддерживает команду IMAP THREAD (поток) (автор: Yves Dionne) и новые методы `deleteacl()` и `myrights()` (автор: Arnaud Mazin).714- В модуле [`itertools`](https://python-all.ru/3.13/library/itertools.html#module-itertools) появилась функция `groupby(iterable[, *func*])`. *Итерируемый объект* – это то, что можно перебирать для получения потока элементов, а необязательный параметр *func* – функция, которая принимает элемент и возвращает значение ключа; если он опущен, ключом служит сам элемент. `groupby()` затем группирует элементы в подпоследовательности с совпадающими значениями ключа и возвращает серию кортежей из двух элементов, содержащих значение ключа и итератор по подпоследовательности.715716 Вот пример для наглядности. Функция *key* просто возвращает, является ли число чётным или нечётным, так что результат `groupby()` – это последовательные группы нечётных или чётных чисел.717718 ```python719 >>> import itertools720 >>> L = [2, 4, 6, 7, 8, 9, 11, 12, 14]721 >>> for key_val, it in itertools.groupby(L, lambda x: x % 2):722 ... print key_val, list(it)723 ...724 0 [2, 4, 6]725 1 [7]726 0 [8]727 1 [9, 11]728 0 [12, 14]729 >>>730 ```731732 `groupby()` обычно используется с отсортированными входными данными. Логика `groupby()` похожа на фильтр Unix `uniq`, что удобно для удаления, подсчёта или идентификации дублирующихся элементов:733734 ```python735 >>> word = 'abracadabra'736 >>> letters = sorted(word) # преобразовать строку в отсортированный список букв737 >>> letters738 ['a', 'a', 'a', 'a', 'a', 'b', 'b', 'c', 'd', 'r', 'r']739 >>> for k, g in itertools.groupby(letters):740 ... print k, list(g)741 ...742 a ['a', 'a', 'a', 'a', 'a']743 b ['b', 'b']744 c ['c']745 d ['d']746 r ['r', 'r']747 >>> # вывести уникальные буквы748 >>> [k for k, g in groupby(letters)]749 ['a', 'b', 'c', 'd', 'r']750 >>> # подсчитать количество вхождений букв751 >>> [(k, len(list(g))) for k, g in groupby(letters)]752 [('a', 5), ('b', 2), ('c', 1), ('d', 1), ('r', 2)]753 ```754755 (Добавлено Hye-Shik Chang.)756- В модуле [`itertools`](https://python-all.ru/3.13/library/itertools.html#module-itertools) также появилась функция `tee(iterator, N)`, которая возвращает *N* независимых итераторов, копирующих *iterator*. Если *N* опущено, по умолчанию используется 2.757758 ```python759 >>> L = [1,2,3]760 >>> i1, i2 = itertools.tee(L)761 >>> i1,i2762 (<itertools.tee object at 0x402c2080>, <itertools.tee object at 0x402c2090>)763 >>> list(i1) # исчерпать первый итератор764 [1, 2, 3]765 >>> list(i2) # исчерпать второй итератор766 [1, 2, 3]767 ```768769 Обратите внимание, что `tee()` вынужден хранить копии значений, возвращаемых итератором; в худшем случае может потребоваться сохранить их все. Поэтому его следует использовать с осторожностью, если ведущий итератор может сильно опережать ведомый в длинной последовательности входных данных. Если разрыв велик, лучше использовать [`list()`](https://python-all.ru/3.13/library/stdtypes.html#list). Когда итераторы движутся почти синхронно, `tee()` идеален. Возможные применения включают итераторы для закладок, оконного просмотра или опережающего чтения. (Добавлено Raymond Hettinger.)770- В модуль [`locale`](https://python-all.ru/3.13/library/locale.html#module-locale) было добавлено несколько функций, например, `bind_textdomain_codeset()` для указания конкретной кодировки и семейство функций `l*gettext()`, возвращающих сообщения в выбранной кодировке. (Добавлено Gustavo Niemeyer.)771- В функцию `basicConfig()` пакета [`logging`](https://python-all.ru/3.13/library/logging.html#module-logging) были добавлены некоторые именованные аргументы для упрощения настройки логирования. По умолчанию сообщения выводятся в стандартный поток ошибок, но можно указать различные именованные аргументы, чтобы вести журнал в определённый файл, изменить формат логирования или установить уровень журналирования. Например:772773 ```python774 import logging775 logging.basicConfig(filename='/var/log/application.log',776 level=0, # записать все сообщения в лог777 format='%(levelname):%(process):%(thread):%(message)')778 ```779780 Другие дополнения пакета [`logging`](https://python-all.ru/3.13/library/logging.html#module-logging) включают удобный метод `log(level, msg)`, а также класс `TimedRotatingFileHandler`, который циклически перезаписывает файлы журнала через заданный интервал времени. В модуле уже был `RotatingFileHandler`, который перезаписывал журналы по достижении файлом определённого размера. Оба класса наследуются от нового класса `BaseRotatingHandler`, который можно использовать для реализации других обработчиков ротации.781782 (Изменения внесены Vinay Sajip.)783- Модуль [`marshal`](https://python-all.ru/3.13/library/marshal.html#module-marshal) теперь использует интернированные строки при распаковке структуры данных. Это может уменьшить размер некоторых строк pickle, но основной эффект – значительное уменьшение размера файлов `.pyc`. (Добавлено Martin von Löwis.)784- Класс `NNTP` модуля `nntplib` получил методы `description()` и `descriptions()` для получения описаний новостных групп для одной группы или для диапазона групп. (Добавлено Jürgen A. Erhard.)785- В модуль [`operator`](https://python-all.ru/3.13/library/operator.html#module-operator) были добавлены две новые функции: `attrgetter(attr)` и `itemgetter(index)`. Обе функции возвращают вызываемые объекты, которые принимают один аргумент и возвращают соответствующий атрибут или элемент; эти вызываемые объекты отлично подходят для извлечения данных при использовании с [`map()`](https://python-all.ru/3.13/library/functions.html#map) или [`sorted()`](https://python-all.ru/3.13/library/functions.html#sorted). Например:786787 ```python788 >>> L = [('c', 2), ('d', 1), ('a', 4), ('b', 3)]789 >>> map(operator.itemgetter(0), L)790 ['c', 'd', 'a', 'b']791 >>> map(operator.itemgetter(1), L)792 [2, 1, 4, 3]793 >>> sorted(L, key=operator.itemgetter(1)) # отсортировать список по второму элементу кортежа794 [('d', 1), ('c', 2), ('b', 3), ('a', 4)]795 ```796797 (Автор: Raymond Hettinger.)798- Модуль [`optparse`](https://python-all.ru/3.13/library/optparse.html#module-optparse) был обновлён различными способами. Теперь он пропускает свои сообщения через [`gettext.gettext()`](https://python-all.ru/3.13/library/gettext.html#gettext.gettext), что позволяет интернационализировать справочные сообщения и сообщения об ошибках Optik. В справочные сообщения для параметров теперь можно включать строку `'%default'`, которая будет заменена на значение параметра по умолчанию. (Добавлено Greg Ward.)799- Долгосрочный план – объявить модуль `rfc822` устаревшим в одном из будущих релизов Python в пользу пакета [`email`](https://python-all.ru/3.13/library/email.html#module-email). С этой целью функция [`email.Utils.formatdate`](https://python-all.ru/3.13/library/email.utils.html#email.utils.formatdate) была изменена, чтобы её можно было использовать как замену для `rfc822.formatdate()`. Возможно, вам стоит писать новый код для обработки электронной почты с учётом этого. (Изменения внесены Anthony Baxter.)800- В модуль [`os`](https://python-all.ru/3.13/library/os.html#module-os) была добавлена новая функция `urandom(n)`, возвращающая строку, содержащую *n* байт случайных данных. Эта функция предоставляет доступ к платформозависимым источникам случайности, таким как `/dev/urandom` в Linux или Windows CryptoAPI. (Добавлено Trevor Perrin.)801- Ещё одна новая функция: `os.path.lexists(path)` возвращает true, если файл, указанный в *path*, существует, независимо от того, является ли он символической ссылкой. Это отличается от существующей функции `os.path.exists(path)`, которая возвращает false, если *path* является симлинком, указывающим на несуществующий целевой объект. (Добавлено Beni Cherniavsky.)802- В модуль [`posix`](https://python-all.ru/3.13/library/posix.html#module-posix), лежащий в основе модуля [`os`](https://python-all.ru/3.13/library/os.html#module-os), добавлена новая функция `getsid()`. (Добавлено J. Raynor.)803- Модуль [`poplib`](https://python-all.ru/3.13/library/poplib.html#module-poplib) теперь поддерживает POP через SSL. (Добавлено Hector Urtubia.)804- Модуль [`profile`](https://python-all.ru/3.13/library/profile.html#module-profile) теперь может профилировать функции-расширения на C. (Добавлено Nick Bastin.)805- В модуле [`random`](https://python-all.ru/3.13/library/random.html#module-random) появился новый метод `getrandbits(N)`, который возвращает длинное целое длиной в *N* бит. Существующий метод `randrange()` теперь использует `getrandbits()` где это уместно, что делает генерацию произвольно больших случайных чисел более эффективной. (Добавлено Raymond Hettinger.)806- Язык регулярных выражений, принимаемый модулем [`re`](https://python-all.ru/3.13/library/re.html#module-re), был расширен простыми условными выражениями, записываемыми как `(?(group)A|B)`. *group* – это либо числовой идентификатор группы, либо имя группы, определенное с помощью `(?P<group>...)` ранее в выражении. Если указанная группа совпала, шаблон регулярного выражения *A* будет проверяться на строке; если группа не совпала, вместо него будет использоваться шаблон *B*. (Добавлено Gustavo Niemeyer.)807- Модуль [`re`](https://python-all.ru/3.13/library/re.html#module-re) больше не является рекурсивным, благодаря огромной работе Gustavo Niemeyer. В рекурсивном движке регулярных выражений некоторые шаблоны приводят к потреблению большого объёма памяти в стеке C, и можно было переполнить стек. Например, если сопоставить 30000-байтовую строку из символов `a` с выражением `(a|b)+`, расходуется один кадр стека на символ. Python 2.3 пытался проверять переполнение стека и возбуждать исключение [`RuntimeError`](https://python-all.ru/3.13/library/exceptions.html#RuntimeError), но некоторые шаблоны могли обойти проверку, и при невезении Python мог упасть с segfault. Движок регулярных выражений Python 2.4 может сопоставлять этот шаблон без проблем.808- Модуль [`signal`](https://python-all.ru/3.13/library/signal.html#module-signal) теперь выполняет более строгую проверку ошибок в параметрах функции [`signal.signal()`](https://python-all.ru/3.13/library/signal.html#signal.signal). Например, нельзя установить обработчик на сигнал `SIGKILL`; предыдущие версии Python молча принимали это, но 2.4 возбудит исключение [`RuntimeError`](https://python-all.ru/3.13/library/exceptions.html#RuntimeError).809- В модуль [`socket`](https://python-all.ru/3.13/library/socket.html#module-socket) добавлены две новые функции. `socketpair()` возвращает пару соединённых сокетов, а `getservbyport(port)` ищет имя службы для заданного номера порта. (Добавлено Dave Cole и Barry Warsaw.)810- Функция `sys.exitfunc()` объявлена устаревшей. Код должен использовать существующий модуль [`atexit`](https://python-all.ru/3.13/library/atexit.html#module-atexit), который правильно обрабатывает вызов нескольких функций завершения. В конечном итоге `sys.exitfunc()` станет чисто внутренним интерфейсом, доступным только через `atexit`.811- Модуль [`tarfile`](https://python-all.ru/3.13/library/tarfile.html#module-tarfile) теперь по умолчанию создаёт tar-файлы в формате GNU. (Добавлено Lars Gustäbel.)812- Модуль [`threading`](https://python-all.ru/3.13/library/threading.html#module-threading) теперь имеет элегантно простой способ поддержки потоково-локальных данных. Модуль содержит класс `local`, значения атрибутов которого являются локальными для разных потоков.813814 ```python815 import threading816817 data = threading.local()818 data.number = 42819 data.url = ('www.python.org', 80)820 ```821822 Другие потоки могут присваивать и получать свои собственные значения для атрибутов `number` и `url`. Можно создать подкласс `local` для инициализации атрибутов или добавления методов. (Добавлено Jim Fulton.)823- Модуль [`timeit`](https://python-all.ru/3.13/library/timeit.html#module-timeit) теперь автоматически отключает периодическую сборку мусора во время цикла замеров. Это изменение делает последовательные замеры времени более сопоставимыми. (Добавлено Raymond Hettinger.)824- Модуль [`weakref`](https://python-all.ru/3.13/library/weakref.html#module-weakref) теперь поддерживает более широкий спектр объектов, включая функции Python, экземпляры классов, множества, frozenset, deque, массивы, файлы, сокеты и объекты шаблонов регулярных выражений. (Добавлено Raymond Hettinger.)825- Модуль [`xmlrpclib`](https://python-all.ru/3.13/library/xmlrpc.client.html#module-xmlrpc.client) теперь поддерживает расширение multi-call для передачи нескольких XML-RPC-вызовов в одной HTTP-операции. (Автор: Брайан Куинлан.)826- Модули `mpz`, `rotor` и `xreadlines` были удалены.827828### cookielib829830Библиотека [`cookielib`](https://python-all.ru/3.13/library/http.cookiejar.html#module-http.cookiejar) поддерживает обработку HTTP-куки на стороне клиента, зеркально отражая поддержку куки на стороне сервера модулем [`Cookie`](https://python-all.ru/3.13/library/http.cookies.html#module-http.cookies). Куки хранятся в хранилищах cookie jar; библиотека прозрачно сохраняет куки, предлагаемые веб-сервером, в хранилище и извлекает куки из хранилища при подключении к серверу. Как и в веб-браузерах, объекты политики управляют принятием или отклонением куки.831832Для сохранения куки между сеансами предоставляются две реализации хранилищ: одна хранит куки в формате Netscape, чтобы приложения могли использовать файлы куки Mozilla или Lynx, а другая хранит куки в том же формате, что и библиотека Perl libwww.833834[`urllib2`](https://python-all.ru/3.13/library/urllib.request.html#module-urllib.request) был изменён для взаимодействия с [`cookielib`](https://python-all.ru/3.13/library/http.cookiejar.html#module-http.cookiejar): `HTTPCookieProcessor` управляет хранилищем куки, которое используется при доступе к URL.835836Этот модуль был предоставлен Джоном Дж. Ли.837838### doctest839840Модуль [`doctest`](https://python-all.ru/3.13/library/doctest.html#module-doctest) подвергся существенному рефакторингу благодаря Эдварду Лоперу и Тиму Питерсу. Тестирование по-прежнему может быть таким же простым, как запуск [`doctest.testmod()`](https://python-all.ru/3.13/library/doctest.html#doctest.testmod), но рефакторинг позволяет настраивать работу модуля различными способами841842Новый класс `DocTestFinder` извлекает тесты из docstrings переданного объекта:843844```python845def f (x, y):846 """>>> f(2,2)8474848>>> f(3,2)8496850 """851 return x*y852853finder = doctest.DocTestFinder()854855# получить список экземпляров DocTest856tests = finder.find(f)857```858859Новый класс `DocTestRunner` затем запускает отдельные тесты и может создать сводку результатов:860861```python862runner = doctest.DocTestRunner()863for t in tests:864 tried, failed = runner.run(t)865866runner.summarize(verbose=1)867```868869Приведённый выше пример даёт следующий вывод:870871```python8721 items passed all tests:873 2 tests in f8742 tests in 1 items.8752 passed and 0 failed.876Test passed.877```878879`DocTestRunner` использует экземпляр класса `OutputChecker` для сравнения ожидаемого вывода с фактическим выводом. Этот класс принимает ряд различных флагов, настраивающих его поведение; амбициозные пользователи также могут написать полностью новый подкласс `OutputChecker`.880881Стандартный проверяющий вывод предоставляет ряд удобных возможностей. Например, с флагом [`doctest.ELLIPSIS`](https://python-all.ru/3.13/library/doctest.html#doctest.ELLIPSIS) многоточие (`...`) в ожидаемом выводе соответствует любой подстроке, что упрощает адаптацию к выводам, которые незначительно различаются:882883```python884def o (n):885 """>>> o(1)886<__main__.C instance at 0x...>887>>>888"""889```890891Другая специальная строка `<BLANKLINE>` соответствует пустой строке:892893```python894def p (n):895 """>>> p(1)896<BLANKLINE>897>>>898"""899```900901Ещё одна новая возможность – создание отображения вывода в стиле diff путём указания флагов [`doctest.REPORT_UDIFF`](https://python-all.ru/3.13/library/doctest.html#doctest.REPORT_UDIFF) (unified diffs), [`doctest.REPORT_CDIFF`](https://python-all.ru/3.13/library/doctest.html#doctest.REPORT_CDIFF) (context diffs) или [`doctest.REPORT_NDIFF`](https://python-all.ru/3.13/library/doctest.html#doctest.REPORT_NDIFF) (delta-style). Например:902903```python904def g (n):905 """>>> g(4)906здесь907есть908a909длинный910>>>"""911 L = 'here is a rather lengthy list of words'.split()912 for word in L[:n]:913 print word914```915916При запуске тестов вышеуказанной функции с указанием [`doctest.REPORT_UDIFF`](https://python-all.ru/3.13/library/doctest.html#doctest.REPORT_UDIFF) вы получите следующий вывод:917918```text919**********************************************************************920File "t.py", line 15, in g921Failed example:922 g(4)923Differences (unified diff with -expected +actual):924 @@ -2,3 +2,3 @@925 is926 a927 -lengthy928 +rather929**********************************************************************930```931932## Изменения в сборке и C API933934Некоторые из изменений в процессе сборки Python и в C API:935936- Были добавлены три новых удобных макроса для распространённых возвращаемых значений функций расширений: [`Py_RETURN_NONE`](https://python-all.ru/3.13/c-api/none.html#c.Py_RETURN_NONE), [`Py_RETURN_TRUE`](https://python-all.ru/3.13/c-api/bool.html#c.Py_RETURN_TRUE) и [`Py_RETURN_FALSE`](https://python-all.ru/3.13/c-api/bool.html#c.Py_RETURN_FALSE). (Автор: Бретт Кэннон.)937- Ещё один новый макрос [`Py_CLEAR`](https://python-all.ru/3.13/c-api/refcounting.html#c.Py_CLEAR) уменьшает счётчик ссылок объекта *obj* и устанавливает *obj* в нулевой указатель. (Автор: Джим Фултон.)938- Новая функция `PyTuple_Pack(N, obj1, obj2, ..., objN)` создаёт кортежи из списка аргументов переменной длины объектов Python. (Автор: Реймонд Хеттингер.)939- Новая функция `PyDict_Contains(d, k)` реализует быстрый поиск в словаре без маскировки исключений, возникших в процессе поиска. (Автор: Реймонд Хеттингер.)940- Макрос [Py\_IS\_NAN](https://python-all.ru/3.13/c-api/float.html#c.Py_IS_NAN)(X) возвращает 1, если его аргумент типа float или double *X* является NaN. (Автор: Тим Питерс.)941- C-код может избежать ненужной блокировки, используя новую функцию `PyEval_ThreadsInitialized()`, чтобы узнать, выполнялись ли какие-либо операции с потоками. Если эта функция возвращает false, никакие операции блокировки не требуются. (Автор: Ник Коглан.)942- Новая функция [`PyArg_VaParseTupleAndKeywords()`](https://python-all.ru/3.13/c-api/arg.html#c.PyArg_VaParseTupleAndKeywords) аналогична [`PyArg_ParseTupleAndKeywords()`](https://python-all.ru/3.13/c-api/arg.html#c.PyArg_ParseTupleAndKeywords), но принимает `va_list` вместо количества аргументов. (Автор: Грег Чепмен.)943- Новый флаг метода [`METH_COEXIST`](https://python-all.ru/3.13/c-api/structures.html#c.METH_COEXIST) позволяет функции, определённой в слотах, сосуществовать с [`PyCFunction`](https://python-all.ru/3.13/c-api/structures.html#c.PyCFunction), имеющим то же имя. Это может вдвое сократить время доступа к такому методу, как `set.__contains__()`. (Автор: Реймонд Хеттингер.)944- Python теперь может быть собран с дополнительным профилированием самого интерпретатора, предназначенным для помощи разработчикам ядра Python. Указание `--enable-profiling` сценарию **configure** позволит вам профилировать интерпретатор с помощью **gprof**, а указание ключа `--with-tsc` включает профилирование с использованием регистра счётчика временных меток Pentium. Обратите внимание, что ключ `--with-tsc` назван немного неправильно, поскольку функция профилирования также работает на платформе PowerPC, хотя эта архитектура процессора не называет этот регистр «регистром TSC». (Автор: Джереми Хилтон.)945- Тип `tracebackobject` был переименован в `PyTracebackObject`.946947### Изменения, специфичные для платформ948949- Версия для Windows теперь собирается в MSVC++ 7.1, а также в версии 6. (Автор: Мартин фон Лёвис.)950951## Переход на Python 2.4952953В этом разделе перечислены описанные ранее изменения, которые могут потребовать изменения кода:954955- Сдвиги влево и шестнадцатеричные/восьмеричные константы, которые слишком велики, больше не вызывают [`FutureWarning`](https://python-all.ru/3.13/library/exceptions.html#FutureWarning) и не возвращают значение, ограниченное 32 или 64 битами; вместо этого они возвращают длинное целое число.956- Целочисленные операции больше не будут вызывать `OverflowWarning`. Предупреждение `OverflowWarning` исчезнет в Python 2.5.957- Встроенная функция [`zip()`](https://python-all.ru/3.13/library/functions.html#zip) и `itertools.izip()` теперь возвращают пустой список вместо возбуждения исключения [`TypeError`](https://python-all.ru/3.13/library/exceptions.html#TypeError), если вызваны без аргументов.958- Сравнение экземпляров `date` и [`datetime`](https://python-all.ru/3.13/library/datetime.html#datetime.datetime), предоставляемых модулем [`datetime`](https://python-all.ru/3.13/library/datetime.html#module-datetime), больше не допускается. Два экземпляра разных классов теперь всегда будут неравными, а операции относительного сравнения (`<`, `>`) будут возбуждать [`TypeError`](https://python-all.ru/3.13/library/exceptions.html#TypeError).959- `dircache.listdir()` теперь передаёт исключения вызывающему коду вместо возврата пустых списков.960- `LexicalHandler.startDTD()` раньше получал публичные и системные идентификаторы в неправильном порядке. Это исправлено; приложения, полагающиеся на неправильный порядок, необходимо исправить.961- [`fcntl.ioctl()`](https://python-all.ru/3.13/library/fcntl.html#fcntl.ioctl) теперь выдаёт предупреждение, если аргумент *mutate* опущен и это имеет значение.962- Модуль [`tarfile`](https://python-all.ru/3.13/library/tarfile.html#module-tarfile) теперь по умолчанию создаёт tar-файлы в формате GNU.963- Ошибка при импорте модуля больше не оставляет частично инициализированный объект модуля в `sys.modules`.964- [`None`](https://python-all.ru/3.13/library/constants.html#None) теперь является константой; код, присваивающий новое значение имени `None`, теперь вызывает синтаксическую ошибку.965- Функция `signals.signal()` теперь возбуждает исключение [`RuntimeError`](https://python-all.ru/3.13/library/exceptions.html#RuntimeError) для некоторых недопустимых значений; ранее эти ошибки проходили незамеченными. Например, больше нельзя установить обработчик на сигнал `SIGKILL`.966967## Благодарности968969Автор хотел бы поблагодарить следующих людей за предложения, исправления и помощь в работе над различными черновиками этой статьи: Koray Can, Hye-Shik Chang, Michael Dyck, Raymond Hettinger, Brian Hurt, Hamish Lawson, Fredrik Lundh, Sean Reifschneider, Sadruddin Rejeb.970