2.4.md
1> **Источник:** https://python-all.ru/3.4/whatsnew/2.4.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# Что нового в Python 2.489| Автор: | A.M. Kuchling |10| --- | --- |1112В этой статье описываются новые возможности Python 2.4.1, выпущенного 30 марта, 2005.1314Python 2.4 – релиз среднего размера. Он не вносит столько изменений, как радикальный Python 2.2, но добавляет больше возможностей, чем консервативный 2.3 релиз. Наиболее значительные новые языковые возможности – это декораторы функций и выражения-генераторы; большинство остальных изменений касаются стандартной библиотеки.1516Согласно журналам изменений CVS, между Python 2.3 и 2.4 было применено 481 исправление и исправлено 502 ошибки. Обе цифры, скорее всего, занижены.1718Эта статья не ставит целью дать полную спецификацию каждой новой возможности, а вместо этого предоставляет краткое введение в каждую из них. За полными подробностями следует обращаться к документации Python 2.4, например, к справочнику по библиотеке Python и руководству по языку Python. Часто вас будут отсылать к PEP для конкретной новой возможности, где объясняются детали реализации и обоснование проекта.1920## PEP 218: Встроенные объекты множеств2122В Python 2.3 был представлен модуль `sets`. Теперь в ядро Python добавлены реализации на C типов данных set в виде двух новых встроенных типов: `set(iterable)` и `frozenset(iterable)`. Они обеспечивают высокоскоростные операции для проверки принадлежности, удаления дубликатов из последовательностей, а также для математических операций, таких как объединение, пересечение, разность и симметрическая разность.2324```python25>>> a = set('abracadabra') # Сформировать множество из строки26>>> 'z' in a # быстрая проверка принадлежности27False28>>> a # уникальные буквы в a29set(['a', 'r', 'b', 'c', 'd'])30>>> ''.join(a) # Преобразовать обратно в строку31'arbcd'3233>>> b = set('alacazam') # Сформировать второе множество34>>> a - b # буквы, которые есть в a, но нет в b35set(['r', 'd', 'b'])36>>> a | b # Буквы из a или b37set(['a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'])38>>> a & b # буквы, которые есть и в a, и в b39set(['a', 'c'])40>>> a ^ b # буквы, которые есть в a или в b, но не в обоих41set(['r', 'd', 'b', 'm', 'z', 'l'])4243>>> a.add('z') # Добавить новый элемент44>>> a.update('wxy') # Добавить несколько новых элементов45>>> a46set(['a', 'c', 'b', 'd', 'r', 'w', 'y', 'x', 'z'])47>>> a.remove('x') # извлечь один элемент48>>> a49set(['a', 'c', 'b', 'd', 'r', 'w', 'y', 'z'])50```5152Тип [`frozenset()`](https://python-all.ru/3.4/library/stdtypes.html#frozenset) является неизменяемой версией [`set()`](https://python-all.ru/3.4/library/stdtypes.html#set). Поскольку он неизменяем и хешируем, его можно использовать в качестве ключа словаря или как элемент другого множества.5354Модуль `sets` остаётся в стандартной библиотеке и может быть полезен, если вы хотите создать подкласс классов `Set` или `ImmutableSet`. В настоящее время нет планов объявлять модуль устаревшим.5556> **См. также**57>58> **[**PEP 218**](https://python-all.ru/3.4/whatsnew/2.4.html) – Добавление встроенного типа объектов-множеств**59>60> Изначально предложено Грегом Уилсоном, окончательно реализовано Рэймондом Хеттингером.6162## PEP 237: Унификация длинных целых и целых чисел6364Длительный процесс перехода по этому PEP, начатый в Python 2.2, делает очередной шаг вперёд в Python 2.4. В версии 2.3 некоторые целочисленные операции, которые вели бы себя иначе после унификации int/long, вызывали предупреждения [`FutureWarning`](https://python-all.ru/3.4/library/exceptions.html#FutureWarning) и возвращали значения, ограниченные 32 или 64 битами (в зависимости от вашей платформы). В версии 2.4 эти выражения больше не генерируют предупреждение, а вместо этого возвращают другой результат, который обычно является длинным целым.6566Проблемные выражения – это в основном сдвиги влево и длинные шестнадцатеричные и восьмеричные константы. Например, `2 << 32` в 2.3 вызывает предупреждение, вычисляясь в 0 на 32-битных платформах. В Python 2.4 это выражение теперь возвращает правильный ответ: 8589934592.6768> **См. также**69>70> **[**PEP 237**](https://python-all.ru/3.4/whatsnew/2.4.html) – Унификация длинных целых и целых чисел**71>72> Оригинальный PEP написан Моше Задкой и GvR. Изменения для 2.4 были реализованы Калле Свенссоном.7374## PEP 289: Выражения-генераторы7576Возможность итераторов, введённая в Python 2.2, и модуль [`itertools`](https://python-all.ru/3.4/library/itertools.html#module-itertools) упрощают написание программ, которые проходят по большим наборам данных без необходимости держать весь набор данных в памяти одновременно. Списковые включения не очень вписываются в эту картину, потому что они создают объект списка Python, содержащий все элементы. Это неизбежно загружает все объекты в память, что может быть проблемой, если ваш набор данных очень велик. При попытке написать программу в функциональном стиле было бы естественно написать что-то вроде:7778```python79links = [link for link in get_all_links() if not link.followed]80for link in links:81 ...82```8384вместо8586```python87for link in get_all_links():88 if link.followed:89 continue90 ...91```9293Первая форма более лаконична и, возможно, более читаема, но если вы работаете с большим количеством объектов ссылок, вам придётся писать вторую форму, чтобы избежать одновременного хранения всех объектов ссылок в памяти.9495Выражения-генераторы работают аналогично списковым включениям, но не материализуют весь список; вместо этого они создают генератор, который будет возвращать элементы один за другим. Приведённый выше пример можно записать так:9697```python98links = (link for link in get_all_links() if not link.followed)99for link in links:100 ...101```102103Выражения-генераторы всегда должны быть заключены в круглые скобки, как в приведённом выше примере. Скобки, обозначающие вызов функции, тоже подходят, поэтому если вы хотите создать итератор, который будет немедленно передан функции, вы можете написать:104105```python106print sum(obj.count for obj in list_all_objects())107```108109Выражения-генераторы отличаются от списковых включений в различных мелочах. Наиболее заметно, что переменная цикла (*obj* в примере выше) недоступна за пределами выражения-генератора. Списковые включения оставляют переменную присвоенной её последнему значению; будущие версии Python изменят это, сделав списковые включения соответствующими выражениям-генераторам в этом отношении.110111> **См. также**112>113> **[**PEP 289**](https://python-all.ru/3.4/whatsnew/2.4.html) – Выражения-генераторы**114>115> Предложено Рэймондом Хеттингером, реализовано Дживоном Сео при ранних усилиях, направляемых Хе-Шиком Чаном.116117## PEP 292: Более простые подстановки в строках118119Некоторые новые классы в стандартной библиотеке предоставляют альтернативный механизм для подстановки переменных в строки; этот стиль подстановки может быть лучше для приложений, где неподготовленным пользователям нужно редактировать шаблоны.120121Обычный способ подстановки переменных по имени – оператор `%`:122123```python124>>> '%(page)i: %(title)s' % {'page':2, 'title': 'The Best of Times'}125'2: The Best of Times'126```127128При написании строки шаблона легко забыть `i` или `s` после закрывающей скобки. Это не большая проблема, если шаблон находится в модуле Python, потому что вы запускаете код, получаете «Unsupported format character» [`ValueError`](https://python-all.ru/3.4/library/exceptions.html#ValueError) и исправляете проблему. Однако рассмотрим такое приложение, как Mailman, где строки шаблонов или переводы редактируются пользователями, которые не знакомы с языком Python. Синтаксис форматной строки сложно объяснить таким пользователям, и если они допускают ошибку, трудно предоставить им полезную обратную связь.129130PEP 292 добавляет класс `Template` в модуль [`string`](https://python-all.ru/3.4/library/string.html#module-string), который использует `$` для обозначения подстановки:131132```python133>>> import string134>>> t = string.Template('$page: $title')135>>> t.substitute({'page':2, 'title': 'The Best of Times'})136'2: The Best of Times'137```138139Если ключ отсутствует в словаре, метод `substitute()` вызовет исключение [`KeyError`](https://python-all.ru/3.4/library/exceptions.html#KeyError). Существует также метод `safe_substitute()`, который игнорирует отсутствующие ключи:140141```python142>>> t = string.Template('$page: $title')143>>> t.safe_substitute({'page':3})144'3: $title'145```146147> **См. также**148>149> **[**PEP 292**](https://python-all.ru/3.4/whatsnew/2.4.html) – Упрощённые строковые подстановки**150>151> Написано и реализовано Barry Warsaw.152153## PEP 318: Декораторы функций и методов154155Python 2.2 расширил объектную модель Python, добавив статические методы и методы класса, но не расширил синтаксис Python для предоставления нового способа определения статических методов или методов класса. Вместо этого нужно было написать инструкцию [`def`](https://python-all.ru/3.4/reference/compound_stmts.html#def) обычным образом и передать полученный метод функции [`staticmethod()`](https://python-all.ru/3.4/library/functions.html#staticmethod) или [`classmethod()`](https://python-all.ru/3.4/library/functions.html#classmethod), которая обернула бы функцию как метод нового типа. Ваш код выглядел бы так:156157```python158class C:159 def meth (cls):160 ...161162 meth = classmethod(meth) # перепривязать имя к обёрнутому методу класса163```164165Если метод был очень длинным, было легко пропустить или забыть вызов [`classmethod()`](https://python-all.ru/3.4/library/functions.html#classmethod) после тела функции.166167Всегда предполагалось добавить синтаксис, чтобы сделать такие определения более читаемыми, но на момент выхода 2.2 хороший синтаксис не был очевиден. Сегодня хороший синтаксис *всё ещё* не очевиден, но пользователи просят более простого доступа к этой возможности; был добавлен новый синтаксический элемент для удовлетворения этой потребности.168169Новая возможность называется «декораторы функций». Название происходит от идеи, что [`classmethod()`](https://python-all.ru/3.4/library/functions.html#classmethod), [`staticmethod()`](https://python-all.ru/3.4/library/functions.html#staticmethod) и подобные им хранят дополнительную информацию в объекте функции; они *украшают* функции дополнительными деталями.170171Обозначение заимствовано из Java и использует символ `'@'` как индикатор. С использованием нового синтаксиса приведённый выше пример был бы записан так:172173```python174class C:175176 @classmethod177 def meth (cls):178 ...179```180181Запись `@classmethod` является сокращением для присваивания `meth=classmethod(meth)`. В более общем случае, если у вас есть следующее:182183```python184@A185@B186@C187def f ():188 ...189```190191Это эквивалентно следующему коду без декораторов:192193```python194def f(): ...195f = A(B(C(f)))196```197198Декораторы должны располагаться на строке перед определением функции, по одному декоратору на строку, и не могут находиться на той же строке, что и инструкция def, то есть запись `@A def f(): ...` недопустима. Декорировать можно только определения функций, либо на уровне модуля, либо внутри класса; определения классов декорировать нельзя.199200Декоратор – это просто функция, которая принимает декорируемую функцию в качестве аргумента и возвращает либо ту же функцию, либо какой-то новый объект. Возвращаемое значение декоратора не обязано быть вызываемым (хотя обычно оно вызываемое), если только к результату не будут применяться другие декораторы. Написать собственные декораторы легко. Следующий простой пример просто устанавливает атрибут у объекта функции:201202```python203>>> def deco(func):204... func.attr = 'decorated'205... return func206...207>>> @deco208... def f(): pass209...210>>> f211<function f at 0x402ef0d4>212>>> f.attr213'decorated'214>>>215```216217В качестве чуть более реалистичного примера следующий декоратор проверяет, что переданный аргумент является целым числом:218219```python220def require_int (func):221 def wrapper (arg):222 assert isinstance(arg, int)223 return func(arg)224225 return wrapper226227@require_int228def p1 (arg):229 print arg230231@require_int232def p2(arg):233 print arg*2234```235236Пример в [**PEP 318**](https://python-all.ru/3.4/whatsnew/2.4.html) содержит более продвинутую версию этой идеи, которая позволяет как указать требуемый тип, так и проверить возвращаемый тип.237238Функции-декораторы могут принимать аргументы. Если аргументы переданы, ваша функция-декоратор вызывается только с этими аргументами и должна вернуть новую функцию-декоратор; эта функция должна принимать одну функцию и возвращать функцию, как описано ранее. Другими словами, `@A @B @C(args)` превращается в:239240```python241def f(): ...242_deco = C(args)243f = A(B(_deco(f)))244```245246Правильно реализовать это может быть немного запутанно, но не слишком сложно.247248Небольшое связанное изменение делает атрибут `func_name` функций доступным для записи. Этот атрибут используется для отображения имён функций в трассировках стека, поэтому декораторы должны изменять имя любой новой функции, которая создаётся и возвращается.249250> **См. также**251>252> **[**PEP 318**](https://python-all.ru/3.4/whatsnew/2.4.html) – Декораторы функций, методов и классов**253>254> Авторы: Kevin D. Smith, Jim Jewett и Skip Montanaro. Несколько человек написали патчи, реализующие декораторы функций, но тот, который был фактически включён, – патч #979728, написанный Mark Russell.255>256> **[https://www.python.org/moin/PythonDecoratorLibrary](https://python-all.ru/3.4/whatsnew/2.4.html)**257>258> Эта вики-страница содержит несколько примеров декораторов.259260## PEP 322: Обратная итерация261262Новая встроенная функция `reversed(seq)` принимает последовательность и возвращает итератор, который обходит элементы последовательности в обратном порядке.263264```python265>>> for i in reversed(xrange(1,4)):266... print i267...268326922701271```272273По сравнению с расширенной срезкой, такой как `range(1,4)[::-1]`, функция [`reversed()`](https://python-all.ru/3.4/library/functions.html#reversed) легче читается, работает быстрее и использует значительно меньше памяти.274275Обратите внимание: [`reversed()`](https://python-all.ru/3.4/library/functions.html#reversed) принимает только последовательности, а не произвольные итераторы. Если вы хотите перевернуть итератор, сначала преобразуйте его в список с помощью [`list()`](https://python-all.ru/3.4/library/stdtypes.html#list).276277```python278>>> input = open('/etc/passwd', 'r')279>>> for line in reversed(list(input)):280... print line281...282root:*:0:0:System Administrator:/var/root:/bin/tcsh283 ...284```285286> **См. также**287>288> **[**PEP 322**](https://python-all.ru/3.4/whatsnew/2.4.html) – Обратная итерация**289>290> Написано и реализовано Raymond Hettinger.291292## PEP 324: Новый модуль подпроцесс293294Стандартная библиотека предоставляет множество способов выполнения подпроцесса, предлагая разные возможности и разный уровень сложности. `os.system(command)` прост в использовании, но медленный (он запускает процесс оболочки, которая выполняет команду) и опасный (нужно быть осторожным с экранированием метасимволов оболочки). Модуль `popen2` предоставляет классы, которые могут захватывать стандартный вывод и стандартную ошибку подпроцесса, но названия сбивают с толку. Модуль [`подпроцесса`](https://python-all.ru/3.4/library/subprocess.html#module-subprocess) упорядочивает это, предоставляя единый интерфейс, который включает все необходимые возможности.295296Вместо набора классов `popen2` модуль [`подпроцесса`](https://python-all.ru/3.4/library/subprocess.html#module-subprocess) содержит один класс с именем `Popen`, конструктор которого поддерживает ряд различных именованных аргументов.297298```python299class Popen(args, bufsize=0, executable=None,300 stdin=None, stdout=None, stderr=None,301 preexec_fn=None, close_fds=False, shell=False,302 cwd=None, env=None, universal_newlines=False,303 startupinfo=None, creationflags=0):304```305306*args* обычно представляет собой последовательность строк, которые будут аргументами программы, выполняемой как подпроцесс. (Если аргумент *shell* равен true, *args* может быть строкой, которая затем будет передана оболочке для интерпретации, так же как это делает [`os.system()`](https://python-all.ru/3.4/library/os.html#os.system).)307308*stdin*, *stdout* и *stderr* определяют, какими будут потоки ввода, вывода и ошибок подпроцесса. Можно передать файловый объект или файловый дескриптор, или использовать константу `subprocess.PIPE` для создания канала между подпроцессом и родительским процессом.309310Конструктор имеет ряд удобных опций:311312- *close\_fds* требует, чтобы все файловые дескрипторы были закрыты перед запуском подпроцесса.313- *cwd* указывает рабочий каталог, в котором будет выполняться подпроцесс (по умолчанию используется рабочий каталог родительского процесса).314- *env* – это словарь, задающий переменные окружения.315- *preexec\_fn* – это функция, которая вызывается перед запуском дочернего процесса.316- *universal\_newlines* открывает ввод и вывод дочернего процесса с использованием механизма [*универсальных символов новой строки*](https://python-all.ru/3.4/glossary.html#term-universal-newlines) Python.317318После создания экземпляра `Popen` можно вызвать его метод `wait()`, чтобы приостановить выполнение до выхода подпроцесса, `poll()` – чтобы проверить, завершился ли он без ожидания, или `communicate(data)` для отправки строки *data* на стандартный ввод подпроцесса. Метод `communicate(data)` затем считывает любые данные, которые подпроцесс отправил на стандартный вывод или стандартную ошибку, возвращая кортеж `(stdout_data, stderr_data)`.319320`call()` – это сокращение, которое передаёт свои аргументы конструктору `Popen`, ожидает завершения команды и возвращает код состояния подпроцесса. Он может служить более безопасным аналогом [`os.system()`](https://python-all.ru/3.4/library/os.html#os.system):321322```python323sts = subprocess.call(['dpkg', '-i', '/tmp/new-package.deb'])324if sts == 0:325 # Успех326 ...327else:328 # dpkg вернул ошибку329 ...330```331332Команда выполняется без использования оболочки. Если вы действительно хотите использовать оболочку, можно добавить `shell=True` в качестве именованного аргумента и передать строку вместо последовательности:333334```python335sts = subprocess.call('dpkg -i /tmp/new-package.deb', shell=True)336```337338В PEP приведены различные примеры кода на shell и Python и показано, как их можно преобразовать в код Python, использующий модуль [`подпроцесса`](https://python-all.ru/3.4/library/subprocess.html#module-subprocess). Настоятельно рекомендуется прочитать этот раздел PEP.339340> **См. также**341>342> **[**PEP 324**](https://python-all.ru/3.4/whatsnew/2.4.html) - подпроцесс - новый модуль для работы с процессами**343>344> Написан и реализован Питером Острандом (Peter Åstrand) при содействии Фредрика Лунда (Fredrik Lundh) и других.345346## PEP 327: тип данных Decimal347348Python всегда поддерживал числа с плавающей запятой (FP), основанные на типе C `double`, как тип данных. Однако, хотя большинство языков программирования предоставляют тип с плавающей запятой, многие люди (даже программисты) не знают, что числа с плавающей запятой не представляют некоторые десятичные дроби точно. Новый тип `Decimal` может представлять эти дроби точно, с точностью, задаваемой пользователем.349350### Зачем нужен Decimal?351352Ограничения возникают из-за представления, используемого для чисел с плавающей точкой. Числа с плавающей точкой состоят из трёх компонентов:353354- Знак, который может быть положительным или отрицательным.355- Мантисса, которая представляет собой однозначное двоичное число, за которым следует дробная часть. Например, `1.01` в двоичной записи – это `1 + 0/2 + 1/4`, или 1.25 в десятичной записи.356- Экспонента, которая указывает, где находится десятичная точка в представляемом числе.357358Например, число 1.25 имеет положительный знак, мантиссу 1.01 (в двоичной системе) и экспоненту 0 (десятичную точку сдвигать не нужно). Число 5 имеет те же знак и мантиссу, но экспонента равна 2, потому что мантисса умножается на 4 (2 в степени экспоненты 2); 1.25 \* 4 = 5.359360Современные системы обычно поддерживают числа с плавающей точкой, соответствующие стандарту 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 разрядов, поэтому представление оказывается слегка неточным.361362Иногда эту неточность можно увидеть при выводе числа:363364```python365>>> 1.13661.1000000000000001367```368369Неточность не всегда видна при выводе числа, потому что преобразование числа с плавающей запятой в десятичную строку выполняется библиотекой C, и большинство библиотек C стараются выдавать разумный результат. Однако даже если она не отображается, неточность всё равно присутствует, и последующие операции могут увеличить ошибку.370371Для многих приложений это не имеет значения. Если я строю график точек и отображаю их на мониторе, разница между 1.1 и 1.1000000000000001 слишком мала, чтобы быть заметной. Отчёты часто ограничивают вывод определённым количеством десятичных знаков, и если округлить число до двух, трёх или даже восьми знаков, ошибка никогда не проявляется. Однако для приложений, где это важно, реализация собственных арифметических процедур требует больших усилий.372373Следовательно, был создан тип `Decimal`.374375### Тип `Decimal`376377В стандартную библиотеку Python был добавлен новый модуль [`decimal`](https://python-all.ru/3.4/library/decimal.html#module-decimal). Он содержит два класса: `Decimal` и `Context`. Экземпляры `Decimal` представляют числа, а экземпляры `Context` используются для инкапсуляции различных настроек, таких как точность и режим округления по умолчанию.378379Экземпляры `Decimal` неизменяемы, как обычные целые числа Python и числа с плавающей запятой; после создания нельзя изменить значение, которое представляет экземпляр. Экземпляры `Decimal` можно создавать из целых чисел или строк:380381```python382>>> import decimal383>>> decimal.Decimal(1972)384Decimal("1972")385>>> decimal.Decimal("1.1")386Decimal("1.1")387```388389Также можно передавать кортежи, содержащие знак, мантиссу, представленную в виде кортежа десятичных цифр, и экспоненту:390391```python392>>> decimal.Decimal((1, (1, 4, 7, 5), -2))393Decimal("-14.75")394```395396Предостережение: бит знака – это логическое значение, поэтому 0 означает положительное число, а 1 – отрицательное.397398Преобразование чисел с плавающей запятой создаёт небольшую проблему: должно ли число с плавающей точкой, представляющее 1.1, превращаться в десятичное число для ровно 1.1, или для 1.1 плюс все неточности, которые вносятся? Было решено обойти эту проблему и исключить такое преобразование из API. Вместо этого следует преобразовать число с плавающей запятой в строку с нужной точностью и передать строку конструктору `Decimal`:399400```python401>>> f = 1.1402>>> decimal.Decimal(str(f))403Decimal("1.1")404>>> decimal.Decimal('%.12f' % f)405Decimal("1.100000000000")406```407408Получив экземпляры `Decimal`, можно выполнять над ними обычные математические операции. Есть одно ограничение: для возведения в степень требуется целый показатель степени:409410```python411>>> a = decimal.Decimal('35.72')412>>> b = decimal.Decimal('1.73')413>>> a+b414Decimal("37.45")415>>> a-b416Decimal("33.99")417>>> a*b418Decimal("61.7956")419>>> a/b420Decimal("20.64739884393063583815028902")421>>> a ** 2422Decimal("1275.9184")423>>> a**b424Traceback (most recent call last):425 ...426decimal.InvalidOperation: x ** (non-integer)427```428429Экземпляры `Decimal` можно комбинировать с целыми числами, но не с числами с плавающей запятой:430431```python432>>> a + 4433Decimal("39.72")434>>> a + 4.5435Traceback (most recent call last):436 ...437TypeError: You can interact Decimal only with int, long or Decimal data types.438>>>439```440441Числа `Decimal` можно использовать с модулями [`math`](https://python-all.ru/3.4/library/math.html#module-math) и [`cmath`](https://python-all.ru/3.4/library/cmath.html#module-cmath), но учтите, что перед выполнением операции они будут немедленно преобразованы в числа с плавающей запятой, что может привести к потере точности и правильности. В результате вы также получите обычное число с плавающей запятой, а не `Decimal`.442443```python444>>> import math, cmath445>>> d = decimal.Decimal('123456789012.345')446>>> math.sqrt(d)447351364.18288201344448>>> cmath.sqrt(-d)449351364.18288201344j450```451452Экземпляры `Decimal` имеют метод `sqrt()`, который возвращает `Decimal`, но если нужны другие функции, например тригонометрические, их придётся реализовать самостоятельно.453454```python455>>> d.sqrt()456Decimal("351364.1828820134592177245001")457```458459### Тип `Context`460461Экземпляры класса `Context` инкапсулируют несколько настроек для операций с десятичными числами:462463- `prec` – это точность, количество десятичных знаков.464- `rounding` задаёт режим округления. Модуль [`decimal`](https://python-all.ru/3.4/library/decimal.html#module-decimal) содержит константы для различных вариантов: `ROUND_DOWN`, `ROUND_CEILING`, `ROUND_HALF_EVEN` и другие.465- `traps` – это словарь, определяющий, что происходит при возникновении определённых ошибочных ситуаций: либо возбуждается исключение, либо возвращается значение. Некоторые примеры ошибочных ситуаций: деление на ноль, потеря точности и переполнение.466467Контекст по умолчанию, локальный для потока, доступен при вызове `getcontext()`; можно изменять свойства этого контекста, чтобы менять точность, округление или обработку ловушек. Следующий пример показывает эффект изменения точности контекста по умолчанию:468469```python470>>> decimal.getcontext().prec47128472>>> decimal.Decimal(1) / decimal.Decimal(7)473Decimal("0.1428571428571428571428571429")474>>> decimal.getcontext().prec = 9475>>> decimal.Decimal(1) / decimal.Decimal(7)476Decimal("0.142857143")477```478479Действие по умолчанию для ошибочных ситуаций выбирается; модуль может либо вернуть специальное значение, например, бесконечность или не-число, либо возбудить исключение:480481```python482>>> decimal.Decimal(1) / decimal.Decimal(0)483Traceback (most recent call last):484 ...485decimal.DivisionByZero: x / 0486>>> decimal.getcontext().traps[decimal.DivisionByZero] = False487>>> decimal.Decimal(1) / decimal.Decimal(0)488Decimal("Infinity")489>>>490```491492Экземпляр `Context` также имеет различные методы для форматирования чисел, такие как `to_eng_string()` и `to_sci_string()`.493494Дополнительную информацию можно найти в документации модуля [`decimal`](https://python-all.ru/3.4/library/decimal.html#module-decimal), который включает краткое руководство для начинающих и справочный материал.495496> **См. также**497>498> **[**PEP 327**](https://python-all.ru/3.4/whatsnew/2.4.html) – Десятичный тип данных**499>500> Автор: Facundo Batista, реализовано Facundo Batista, Eric Price, Raymond Hettinger, Aahz и Tim Peters.501>502> **[http://www.lahey.com/float.htm](https://python-all.ru/3.4/whatsnew/2.4.html)**503>504> В статье используется код на Фортране для иллюстрации многих проблем, которые может вызвать неточность вычислений с плавающей запятой.505>506> **[http://www2.hursley.ibm.com/decimal/](https://python-all.ru/3.4/whatsnew/2.4.html)**507>508> Описание представления на основе десятичной системы. Это представление предлагается в качестве стандарта и лежит в основе нового десятичного типа Python. Большая часть этого материала была написана Mike Cowlishaw, разработчиком языка Rexx.509510## PEP 328: Многострочные импорты511512Одно из изменений языка – небольшое синтаксическое улучшение, направленное на упрощение импорта множества имён из модуля. В инструкции `from module import names` параметр *names* представляет собой последовательность имён, разделённых запятыми. Если последовательность очень длинная, можно либо написать несколько инструкций импорта из одного модуля, либо использовать обратную косую черту для переноса строк, например:513514```python515from SimpleXMLRPCServer import SimpleXMLRPCServer,\516 SimpleXMLRPCRequestHandler,\517 CGIXMLRPCRequestHandler,\518 resolve_dotted_attribute519```520521Синтаксическое изменение в Python 2.4 просто позволяет помещать имена в круглые скобки. Python игнорирует переводы строк внутри выражений в скобках, поэтому обратная косая черта больше не нужна:522523```python524from SimpleXMLRPCServer import (SimpleXMLRPCServer,525 SimpleXMLRPCRequestHandler,526 CGIXMLRPCRequestHandler,527 resolve_dotted_attribute)528```529530PEP также предлагает, чтобы все инструкции [`import`](https://python-all.ru/3.4/reference/simple_stmts.html#import) были абсолютными импортами, с ведущим символом `.`, указывающим на относительный импорт. Эта часть PEP не была реализована в Python 2.4, но была завершена в Python 2.5.531532> **См. также**533>534> **[**PEP 328**](https://python-all.ru/3.4/whatsnew/2.4.html) – Импорт: многострочный и абсолютный/относительный**535>536> Автор: Aahz. Многострочные импорты реализованы Dima Dorfman.537538## PEP 331: Преобразования чисел с плавающей запятой/строк, не зависящие от локали539540Модуль [`locale`](https://python-all.ru/3.4/library/locale.html#module-locale) позволяет программам на Python выбирать различные преобразования и соглашения отображения, локализованные для конкретной страны или языка. Однако модуль был осторожен, чтобы не изменять числовую локаль, поскольку различные функции в реализации Python требовали, чтобы числовая локаль оставалась установленной на локаль `'C'`. Часто это происходило из-за того, что код использовал функцию `atof()` из библиотеки C.541542Однако отказ от установки числовой локали вызывал проблемы для расширений, использующих сторонние C-библиотеки, поскольку у них не была установлена правильная локаль. Показательным примером была GTK+, виджеты пользовательского интерфейса которой не отображали числа в текущей локали.543544Решение, описанное в PEP, заключается в добавлении в Python API трёх новых функций, которые выполняют преобразования только в ASCII, игнорируя настройки локали:545546- `PyOS_ascii_strtod(str, ptr)` и `PyOS_ascii_atof(str, ptr)` преобразуют строку в C-тип `double`.547- `PyOS_ascii_formatd(buffer, buf_len, format, d)` преобразует `double` в строку ASCII.548549Код этих функций был взят из библиотеки GLib ([http://library.gnome.org/devel/glib/stable/](https://python-all.ru/3.4/whatsnew/2.4.html)), разработчики которой любезно перелицензировали соответствующие функции и передали их Python Software Foundation. Теперь модуль [`locale`](https://python-all.ru/3.4/library/locale.html#module-locale) может изменять числовую локаль, позволяя таким расширениям, как GTK+, давать правильные результаты.550551> **См. также**552>553> **[**PEP 331**](https://python-all.ru/3.4/whatsnew/2.4.html) – Преобразования чисел с плавающей запятой/строк, не зависящие от локали**554>555> Автор – Christian R. Reis, реализация – Gustavo Carneiro.556557## Прочие изменения языка558559Ниже перечислены все изменения, которые Python 2.4 вносит в ядро языка Python.560561- Добавлены декораторы для функций и методов ([**PEP 318**](https://python-all.ru/3.4/whatsnew/2.4.html)).562- Были добавлены встроенные типы [`set()`](https://python-all.ru/3.4/library/stdtypes.html#set) и [`frozenset()`](https://python-all.ru/3.4/library/stdtypes.html#frozenset) ([**PEP 218**](https://python-all.ru/3.4/whatsnew/2.4.html)). Среди других новых встроенных функций – `reversed(seq)` ([**PEP 322**](https://python-all.ru/3.4/whatsnew/2.4.html)).563- Добавлены генераторные выражения ([**PEP 289**](https://python-all.ru/3.4/whatsnew/2.4.html)).564- Некоторые числовые выражения больше не возвращают значения, ограниченные 32 или 64 битами ([**PEP 237**](https://python-all.ru/3.4/whatsnew/2.4.html)).565- Теперь можно заключать список имён в круглые скобки в инструкции `from module import names` ([**PEP 328**](https://python-all.ru/3.4/whatsnew/2.4.html)).566- Метод [`dict.update()`](https://python-all.ru/3.4/library/stdtypes.html#dict.update) теперь принимает те же формы аргументов, что и конструктор [`dict`](https://python-all.ru/3.4/library/stdtypes.html#dict). Это включает любое отображение, любую итерируемую последовательность пар ключ/значение и именованные аргументы. (Автор – Raymond Hettinger.)567- Строковые методы `ljust()`, `rjust()` и `center()` теперь принимают необязательный аргумент для указания символа заполнения, отличного от пробела. (Автор – Raymond Hettinger.)568- Строки также обзавелись методом `rsplit()`, который работает как метод `split()`, но разбивает строку с конца. (Автор – Sean Reifschneider.)569570 ```python571 >>> 'www.python.org'.split('.', 1)572 ['www', 'python.org']573 'www.python.org'.rsplit('.', 1)574 ['www.python', 'org']575 ```576- Три именованных параметра: *cmp*, *key* и *reverse* – были добавлены в метод `sort()` списков. Эти параметры упрощают некоторые распространённые варианты использования `sort()`. Все эти параметры необязательны.577578 Для параметра *cmp* значением должна быть функция сравнения, которая принимает два параметра и возвращает -1, 0 или +1 в зависимости от результата сравнения. Затем эта функция будет использоваться для сортировки списка. Ранее это был единственный параметр, который можно было передать в `sort()`.579580 *key* должна быть функцией с одним параметром, которая принимает элемент списка и возвращает ключ сравнения для этого элемента. Затем список сортируется с использованием ключей сравнения. Следующий пример сортирует список без учёта регистра:581582 ```python583 >>> L = ['A', 'b', 'c', 'D']584 >>> L.sort() # сортировка с учётом регистра585 >>> L586 ['A', 'D', 'b', 'c']587 >>> # использование параметра 'key' для сортировки списка588 >>> L.sort(key=lambda x: x.lower())589 >>> L590 ['A', 'b', 'c', 'D']591 >>> # старый способ592 >>> L.sort(cmp=lambda x,y: cmp(x.lower(), y.lower()))593 >>> L594 ['A', 'b', 'c', 'D']595 ```596597 Последний пример, в котором используется параметр *cmp*, представляет старый способ выполнения сортировки без учёта регистра. Он работает, но работает медленнее, чем использование параметра *key*. Использование *key* вызывает метод `lower()` один раз для каждого элемента списка, в то время как использование *cmp* вызывает его дважды для каждого сравнения, поэтому использование *key* экономит вызовы метода `lower()`.598599 Для простых ключевых функций и функций сравнения часто можно избежать использования выражения [`lambda`](https://python-all.ru/3.4/reference/expressions.html#lambda), используя вместо этого несвязанный метод. Например, приведённую выше сортировку без учёта регистра лучше всего записать так:600601 ```python602 >>> L.sort(key=str.lower)603 >>> L604 ['A', 'b', 'c', 'D']605 ```606607 Наконец, параметр *reverse* принимает булево значение. Если значение истинно, список будет отсортирован в обратном порядке. Вместо `L.sort(); L.reverse()` теперь можно написать `L.sort(reverse=True)`.608609 Теперь гарантируется, что результаты сортировки устойчивы. Это означает, что две записи с равными ключами будут возвращены в том же порядке, в котором они поступили на вход. Например, можно отсортировать список людей по имени, а затем отсортировать список по возрасту, в результате получится список, отсортированный по возрасту, где люди с одинаковым возрастом находятся в порядке, отсортированном по имени.610611 (Все изменения в `sort()` предоставлены Рэймондом Хеттингером.)612- Появилась новая встроенная функция `sorted(iterable)`, которая работает как метод [`list.sort()`](https://python-all.ru/3.4/library/stdtypes.html#list.sort), изменяющий список на месте, но может использоваться в выражениях. Различия следующие:613- входными данными может быть любой итерируемый объект;614- сортируется новосозданная копия, оригинал остаётся нетронутым; и615- выражение возвращает новую отсортированную копию616617 ```python618 >>> L = [9,7,8,3,2,4,1,6,5]619 >>> [10+i for i in sorted(L)] # можно использовать в списковом включении620 [11, 12, 13, 14, 15, 16, 17, 18, 19]621 >>> L # оригинал остаётся неизменным622 [9,7,8,3,2,4,1,6,5]623 >>> sorted('Monty Python') # любой итерируемый объект может быть входным624 [' ', 'M', 'P', 'h', 'n', 'n', 'o', 'o', 't', 't', 'y', 'y']625626 >>> # вывести содержимое словаря, отсортированное по ключам627 >>> colormap = dict(red=1, blue=2, green=3, black=4, yellow=5)628 >>> for k, v in sorted(colormap.iteritems()):629 ... print k, v630 ...631 black 4632 blue 2633 green 3634 red 1635 yellow 5636 ```637638 (Автор: Raymond Hettinger.)639- Целочисленные операции больше не будут вызывать `OverflowWarning`. Предупреждение `OverflowWarning` исчезнет в Python 2.5.640- Интерпретатор получил новый ключ [*-m*](https://python-all.ru/3.4/using/cmdline.html#cmdoption-m), который принимает имя, ищет соответствующий модуль в `sys.path` и запускает его как сценарий. Например, теперь можно запустить профилировщик Python командой `python -m profile`. (Предоставлено Ником Когланом.)641- Функции `eval(expr, globals, locals)` и `execfile(filename, globals, locals)`, а также оператор `exec` теперь принимают для параметра *locals* любой отображаемый тип. Раньше это должен был быть обычный словарь Python. (Предоставлено Рэймондом Хеттингером.)642- Встроенная функция [`zip()`](https://python-all.ru/3.4/library/functions.html#zip) и `itertools.izip()` теперь возвращают пустой список, если вызваны без аргументов. Раньше они вызывали исключение [`TypeError`](https://python-all.ru/3.4/library/exceptions.html#TypeError). Это делает их более пригодными для использования со списками аргументов переменной длины:643644 ```python645 >>> def transpose(array):646 ... return zip(*array)647 ...648 >>> transpose([(1,2,3), (4,5,6)])649 [(1, 4), (2, 5), (3, 6)]650 >>> transpose([])651 []652 ```653654 (Автор: Raymond Hettinger.)655- При возникновении ошибки во время импорта модуля частично инициализированный объект модуля больше не остаётся в `sys.modules`. Оставшийся неполный объект модуля мог бы ввести в заблуждение последующие импорты того же модуля, заставляя их считаться успешными, что приводило к запутанным ошибкам. (Исправлено Тимом Питерсом.)656- [`None`](https://python-all.ru/3.4/library/constants.html#None) теперь является константой; код, присваивающий новое значение имени `None`, теперь вызывает синтаксическую ошибку. (Предоставлено Рэймондом Хеттингером.)657658### Оптимизации659660- Внутренние циклы для нарезки списков и кортежей были оптимизированы и теперь работают примерно на треть быстрее. Внутренние циклы для словарей также были оптимизированы, что привело к повышению производительности `keys()`, `values()`, `items()`, `iterkeys()`, `itervalues()` и `iteritems()`. (Предоставлено Рэймондом Хеттингером.)661- Механизм увеличения и уменьшения списков был оптимизирован по скорости и эффективности использования памяти. Добавление и извлечение элементов из списков теперь выполняется быстрее благодаря более эффективным путям выполнения и менее частому использованию системной функции `realloc()`. Списковые включения также выигрывают. Метод `list.extend()` также был оптимизирован и больше не преобразует свой аргумент во временный список перед расширением основного списка. (Предоставлено Рэймондом Хеттингером.)662- [`list()`](https://python-all.ru/3.4/library/stdtypes.html#list), [`tuple()`](https://python-all.ru/3.4/library/stdtypes.html#tuple), [`map()`](https://python-all.ru/3.4/library/functions.html#map), [`filter()`](https://python-all.ru/3.4/library/functions.html#filter) и [`zip()`](https://python-all.ru/3.4/library/functions.html#zip) теперь работают в несколько раз быстрее с аргументами, не являющимися последовательностями, которые предоставляют метод [`__len__()`](https://python-all.ru/3.4/reference/datamodel.html#object.__len__). (Предоставлено Рэймондом Хеттингером.)663- Методы `list.__getitem__()`, `dict.__getitem__()` и `dict.__contains__()` теперь реализованы как объекты `method_descriptor` вместо объектов `wrapper_descriptor`. Такая форма доступа удваивает их производительность и делает их более пригодными для использования в качестве аргументов функций высшего порядка: `map(mydict.__getitem__, keylist)`. (Предоставлено Рэймондом Хеттингером.)664- Добавлен новый опкод `LIST_APPEND`, который упрощает генерируемый байт-код для списковых включений и ускоряет их примерно на треть. (Предоставлено Рэймондом Хеттингером.)665- Оптимизатор байткода на маленьких окнах (peephole) был улучшен для создания более короткого и быстрого байткода; примечательно, что результирующий байткод стал более читаемым. (Улучшено Raymond Hettinger.)666- Конкатенация строк в операторах вида `s = s + "abc"` и `s += "abc"` теперь выполняется более эффективно в определённых условиях. Эта оптимизация не будет присутствовать в других реализациях Python, таких как Jython, поэтому не стоит на неё полагаться; для эффективного склеивания большого количества строк по-прежнему рекомендуется использовать метод строк `join()`. (Предоставлено Армином Риго.)667668Итог оптимизаций в версии 2.4: Python 2.4 выполняет тест pystone примерно на 5% быстрее, чем Python 2.3, и на 35% быстрее, чем Python 2.2. (pystone – не самый удачный тест, но это наиболее распространённое измерение производительности Python. Ваши собственные приложения могут получить от Python 2.4 больший или меньший прирост.)669670## Новые, улучшенные и устаревшие модули671672Как обычно, стандартная библиотека Python получила ряд улучшений и исправлений ошибок. Ниже приведён частичный список наиболее заметных изменений, отсортированных по модулям в алфавитном порядке. За более полным списком изменений обращайтесь к файлу `Misc/NEWS` в дереве исходных кодов или просмотрите журналы CVS для получения всех подробностей.673674- Функция `loop()` модуля [`asyncore`](https://python-all.ru/3.4/library/asyncore.html#module-asyncore) теперь имеет параметр *count*, который позволяет выполнять ограниченное количество проходов цикла опроса. По умолчанию цикл по-прежнему выполняется бесконечно.675- Модуль [`base64`](https://python-all.ru/3.4/library/base64.html#module-base64) теперь имеет более полную поддержку RFC 3548 для кодирования и декодирования Base64, Base32 и Base16, включая необязательное преобразование регистра и необязательные альтернативные алфавиты. (Предоставлено Барри Уорсо.)676- Модуль [`bisect`](https://python-all.ru/3.4/library/bisect.html#module-bisect) теперь имеет реализацию на C для повышения производительности. (Предоставлено Дмитрием Васильевым.)677- Коллекции восточноазиатских кодеков CJKCodecs, поддерживаемые Hye-Shik Chang, были интегрированы в версию 2.4. Новые кодировки:678- Китай (КНР): gb2312, gbk, gb18030, big5hkscs, hz679- Китай (Тайвань): big5, cp950680- **Японский: cp932, euc-jis-2004, euc-jp, euc-jisx0213, iso-2022-jp,**681682 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-2004683- Корейский: cp949, euc-kr, johab, iso-2022-kr684- Были добавлены некоторые другие новые кодировки: HP Roman8, ISO\_8859-11, ISO\_8859-16, PCTP-154 и TIS-620.685- Кодеки UTF-8 и UTF-16 теперь лучше справляются с получением частичных входных данных. Раньше класс `StreamReader` пытался прочитать больше данных, что делало невозможным возобновление декодирования из потока. Теперь метод `read()` будет возвращать столько данных, сколько может, а последующие вызовы будут возобновлять декодирование с того места, где остановились предыдущие. (Реализовано Вальтером Дёрвальдом.)686- Появился новый модуль [`collections`](https://python-all.ru/3.4/library/collections.html#module-collections) для различных специализированных типов коллекций. В настоящее время он содержит только один тип – `deque`, двустороннюю очередь, которая эффективно поддерживает добавление и удаление элементов с любого конца:687688 ```python689 >>> from collections import deque690 >>> d = deque('ghi') # создать новый deque с тремя элементами691 >>> d.append('j') # добавить новый элемент справа692 >>> d.appendleft('f') # добавить новый элемент слева693 >>> d # показать представление deque694 deque(['f', 'g', 'h', 'i', 'j'])695 >>> d.pop() # вернуть и удалить правый элемент696 'j'697 >>> d.popleft() # вернуть и удалить левый элемент698 'f'699 >>> list(d) # вывести содержимое deque700 ['g', 'h', 'i']701 >>> 'h' in d # поиск в deque702 True703 ```704705 Некоторые модули, такие как `Queue` и [`threading`](https://python-all.ru/3.4/library/threading.html#module-threading), теперь используют [`collections.deque`](https://python-all.ru/3.4/library/collections.html#collections.deque) для повышения производительности. (Предоставлено Рэймондом Хеттингером.)706- Классы `ConfigParser` были немного улучшены. Метод `read()` теперь возвращает список файлов, которые были успешно обработаны, а метод [`set()`](https://python-all.ru/3.4/library/stdtypes.html#set) вызывает [`TypeError`](https://python-all.ru/3.4/library/exceptions.html#TypeError), если ему передан аргумент *value*, не являющийся строкой. (Предоставлено Джоном Бельмонте и Дэвидом Гуджером.)707- Модуль [`curses`](https://python-all.ru/3.4/library/curses.html#module-curses) теперь поддерживает расширение ncurses `use_default_colors()`. На платформах, где терминал поддерживает прозрачность, это позволяет использовать прозрачный фон. (Предоставлено Йоргом Леманом.)708- Модуль [`difflib`](https://python-all.ru/3.4/library/difflib.html#module-difflib) теперь включает класс `HtmlDiff`, который создаёт HTML-таблицу для параллельного сравнения двух версий текста. (Предоставлено Дэном Гассом.)709- Пакет [`email`](https://python-all.ru/3.4/library/email.html#module-email) был обновлён до версии 3.0, в которой удалены различные устаревшие API и прекращена поддержка Python версий ниже 2.3. Версия 3.0 пакета использует новый инкрементальный парсер для MIME-сообщений, доступный в модуле `email.FeedParser`. Новый парсер не требует чтения всего сообщения в память и не вызывает исключений, если сообщение имеет неправильный формат; вместо этого все проблемы записываются в атрибут `defect` сообщения. (Разработано Энтони Бакстером, Барри Уорсо, Томасом Воутерсом и другими.)710- Модуль [`heapq`](https://python-all.ru/3.4/library/heapq.html#module-heapq) был переписан на C. Полученное десятикратное увеличение скорости делает модуль пригодным для обработки больших объёмов данных. Кроме того, в модуле появились две новые функции `nlargest()` и `nsmallest()`, которые используют кучи для поиска N наибольших или наименьших значений в наборе данных без затрат на полную сортировку. (Предоставлено Рэймондом Хеттингером.)711- Модуль `httplib` теперь содержит константы для HTTP-статусов, определённых в различных RFC-документах, связанных с HTTP. Константы имеют такие имена, как `OK`, `CREATED`, `CONTINUE` и `MOVED_PERMANENTLY`; используйте pydoc, чтобы получить полный список. (Предоставлено Эндрю Эландом.)712- Модуль [`imaplib`](https://python-all.ru/3.4/library/imaplib.html#module-imaplib) теперь поддерживает команду IMAP THREAD (предоставлено Ивом Дионом) и новые методы `deleteacl()` и `myrights()` (предоставлено Арно Мазеном).713- В модуль [`itertools`](https://python-all.ru/3.4/library/itertools.html#module-itertools) добавлена функция `groupby(iterable[, *func*])`. *iterable* – это итерируемый объект, возвращающий последовательность элементов, а необязательный параметр *func* – это функция, которая принимает элемент и возвращает значение ключа; если он опущен, ключом считается сам элемент. Затем `groupby()` группирует элементы в подпоследовательности с одинаковыми значениями ключа и возвращает серию кортежей из двух элементов: значение ключа и итератор по подпоследовательности.714715 Вот пример для наглядности. Функция *key* просто возвращает, чётное число или нечётное, поэтому `groupby()` возвращает последовательные группы чётных или нечётных чисел.716717 ```python718 >>> import itertools719 >>> L = [2, 4, 6, 7, 8, 9, 11, 12, 14]720 >>> for key_val, it in itertools.groupby(L, lambda x: x % 2):721 ... print key_val, list(it)722 ...723 0 [2, 4, 6]724 1 [7]725 0 [8]726 1 [9, 11]727 0 [12, 14]728 >>>729 ```730731 `groupby()` обычно применяется к отсортированным данным. Логика `groupby()` похожа на фильтр `uniq` в Unix, что удобно для удаления, подсчёта или поиска дубликатов:732733 ```python734 >>> word = 'abracadabra'735 >>> letters = sorted(word) # преобразовать строку в отсортированный список букв736 >>> letters737 ['a', 'a', 'a', 'a', 'a', 'b', 'b', 'c', 'd', 'r', 'r']738 >>> for k, g in itertools.groupby(letters):739 ... print k, list(g)740 ...741 a ['a', 'a', 'a', 'a', 'a']742 b ['b', 'b']743 c ['c']744 d ['d']745 r ['r', 'r']746 >>> # вывести уникальные буквы747 >>> [k for k, g in groupby(letters)]748 ['a', 'b', 'c', 'd', 'r']749 >>> # подсчитать количество вхождений букв750 >>> [(k, len(list(g))) for k, g in groupby(letters)]751 [('a', 5), ('b', 2), ('c', 1), ('d', 1), ('r', 2)]752 ```753754 (Добавлено Hye-Shik Chang.)755- В [`itertools`](https://python-all.ru/3.4/library/itertools.html#module-itertools) также появилась функция `tee(iterator, N)`, которая возвращает *N* независимых итераторов, копирующих *iterator*. Если *N* не указан, по умолчанию берётся 2.756757 ```python758 >>> L = [1,2,3]759 >>> i1, i2 = itertools.tee(L)760 >>> i1,i2761 (<itertools.tee object at 0x402c2080>, <itertools.tee object at 0x402c2090>)762 >>> list(i1) # исчерпать первый итератор763 [1, 2, 3]764 >>> list(i2) # исчерпать второй итератор765 [1, 2, 3]766 ```767768 Обратите внимание: `tee()` вынужден хранить копии значений, возвращаемых итератором; в худшем случае может потребоваться сохранить их все. Поэтому эту функцию следует использовать с осторожностью, если ведущий итератор может сильно опередить ведомый при работе с длинной входной последовательностью. Если разрыв велик, лучше вместо этого применить [`list()`](https://python-all.ru/3.4/library/stdtypes.html#list). Когда итераторы движутся близко друг к другу, `tee()` идеален. Возможные применения: закладки, скользящее окно или итераторы с упреждающим чтением. (Автор – Raymond Hettinger.)769- В модуль [`locale`](https://python-all.ru/3.4/library/locale.html#module-locale) добавлено несколько функций, например `bind_textdomain_codeset()` для указания конкретной кодировки и семейство функций `l*gettext()`, возвращающих сообщения в выбранной кодировке. (Автор – Gustavo Niemeyer.)770- В функцию `basicConfig()` пакета [`logging`](https://python-all.ru/3.4/library/logging.html#module-logging) добавлены именованные аргументы для упрощения настройки логирования. По умолчанию сообщения выводятся в стандартный поток ошибок, но с помощью различных именованных аргументов можно указать конкретный файл, изменить формат или установить уровень логирования. Например:771772 ```python773 import logging774 logging.basicConfig(filename='/var/log/application.log',775 level=0, # записать все сообщения в лог776 format='%(levelname):%(process):%(thread):%(message)')777 ```778779 Среди других дополнений пакета [`logging`](https://python-all.ru/3.4/library/logging.html#module-logging) – удобный метод `log(level, msg)` и класс `TimedRotatingFileHandler`, который ротирует файлы журнала через заданные промежутки времени. В модуле уже был `RotatingFileHandler`, ротирующий логи после превышения определённого размера файла. Оба класса наследуются от нового класса `BaseRotatingHandler`, который можно использовать для реализации других обработчиков ротации.780781 (Изменения внесены Vinay Sajip.)782- Модуль [`marshal`](https://python-all.ru/3.4/library/marshal.html#module-marshal) теперь при распаковке структуры данных разделяет интернированные строки. Это может уменьшить размер некоторых pickle-строк, но главный эффект – значительное уменьшение размера файлов `.pyc`. (Автор – Martin von Löwis.)783- Класс `NNTP` модуля [`nntplib`](https://python-all.ru/3.4/library/nntplib.html#module-nntplib) обзавёлся методами `description()` и `descriptions()` для получения описаний групп новостей – как для одной группы, так и для диапазона групп. (Автор – Jürgen A. Erhard.)784- В модуль [`operator`](https://python-all.ru/3.4/library/operator.html#module-operator) добавлены две новые функции: `attrgetter(attr)` и `itemgetter(index)`. Обе возвращают вызываемые объекты, которые принимают один аргумент и возвращают соответствующий атрибут или элемент; эти вызываемые объекты отлично подходят для извлечения данных при использовании с [`map()`](https://python-all.ru/3.4/library/functions.html#map) или [`sorted()`](https://python-all.ru/3.4/library/functions.html#sorted). Например:785786 ```python787 >>> L = [('c', 2), ('d', 1), ('a', 4), ('b', 3)]788 >>> map(operator.itemgetter(0), L)789 ['c', 'd', 'a', 'b']790 >>> map(operator.itemgetter(1), L)791 [2, 1, 4, 3]792 >>> sorted(L, key=operator.itemgetter(1)) # отсортировать список по второму элементу кортежа793 [('d', 1), ('c', 2), ('b', 3), ('a', 4)]794 ```795796 (Автор: Raymond Hettinger.)797- Модуль [`optparse`](https://python-all.ru/3.4/library/optparse.html#module-optparse) был обновлён в разных направлениях. Теперь он передаёт свои сообщения через [`gettext.gettext()`](https://python-all.ru/3.4/library/gettext.html#gettext.gettext), что позволяет интернационализировать справочные сообщения и сообщения об ошибках Optik. В справочные сообщения для опций теперь можно включать строку `'%default'`, которая будет заменена значением опции по умолчанию. (Автор – Greg Ward.)798- В долгосрочной перспективе модуль `rfc822` планируется объявить устаревшим в одной из будущих версий Python в пользу пакета [`email`](https://python-all.ru/3.4/library/email.html#module-email). С этой целью функция `email.Utils.formatdate()` была изменена так, чтобы её можно было использовать как замену `rfc822.formatdate()`. При написании нового кода для обработки электронной почты стоит иметь это в виду. (Изменение реализовано Anthony Baxter.)799- В модуль [`os`](https://python-all.ru/3.4/library/os.html#module-os) добавлена новая функция `urandom(n)`, возвращающая строку, содержащую *n* байтов случайных данных. Эта функция предоставляет доступ к платформенно-зависимым источникам случайности, таким как `/dev/urandom` в Linux или CryptoAPI в Windows. (Автор – Trevor Perrin.)800- Ещё одна новая функция: `os.path.lexists(path)` возвращает true, если файл, указанный в *path*, существует, независимо от того, является ли он символической ссылкой. Это отличается от существующей функции `os.path.exists(path)`, которая возвращает false, если *path* – это символическая ссылка, указывающая на несуществующий объект. (Автор – Beni Cherniavsky.)801- В модуль [`posix`](https://python-all.ru/3.4/library/posix.html#module-posix), лежащий в основе модуля [`os`](https://python-all.ru/3.4/library/os.html#module-os), добавлена новая функция `getsid()`. (Автор – J. Raynor.)802- Модуль [`poplib`](https://python-all.ru/3.4/library/poplib.html#module-poplib) теперь поддерживает POP через SSL. (Автор – Hector Urtubia.)803- Модуль [`profile`](https://python-all.ru/3.4/library/profile.html#module-profile) теперь может профилировать функции-расширения на C. (Автор – Nick Bastin.)804- В модуле [`random`](https://python-all.ru/3.4/library/random.html#module-random) появился новый метод `getrandbits(N)`, возвращающий длинное целое длиной *N* битов. Существующий метод `randrange()` теперь использует `getrandbits()`, где это уместно, что делает генерацию произвольно больших случайных чисел более эффективной. (Автор – Raymond Hettinger.)805- Язык регулярных выражений, поддерживаемый модулем [`re`](https://python-all.ru/3.4/library/re.html#module-re), расширен простыми условными выражениями, записываемыми как `(?(group)A|B)`. *group* – это либо числовой идентификатор группы, либо имя группы, определённое с помощью `(?P<group>...)` ранее в выражении. Если указанная группа совпала, со строкой сопоставляется шаблон *A*; если группа не совпала, используется шаблон *B*. (Автор – Gustavo Niemeyer.)806- Модуль [`re`](https://python-all.ru/3.4/library/re.html#module-re) также больше не является рекурсивным – благодаря огромной работе Густаво Нимейера. В рекурсивном движке регулярных выражений некоторые шаблоны приводили к потреблению большого объёма памяти в стеке C, что могло вызвать переполнение стека. Например, если сопоставить строку из 30000 символов `a` с выражением `(a|b)+`, на каждый символ расходовался один стековый фрейм. Python 2.3 пытался проверять переполнение стека и возбуждать исключение [`RuntimeError`](https://python-all.ru/3.4/library/exceptions.html#RuntimeError), но некоторые шаблоны могли обойти проверку, и при невезении Python падал с segfault. Движок регулярных выражений Python 2.4 обрабатывает этот шаблон без проблем.807- Модуль [`signal`](https://python-all.ru/3.4/library/signal.html#module-signal) теперь выполняет более строгую проверку ошибок для параметров функции [`signal.signal()`](https://python-all.ru/3.4/library/signal.html#signal.signal). Например, нельзя установить обработчик на сигнал `SIGKILL`; предыдущие версии Python молча принимали это, но 2.4 возбудит исключение [`RuntimeError`](https://python-all.ru/3.4/library/exceptions.html#RuntimeError).808- В модуль [`socket`](https://python-all.ru/3.4/library/socket.html#module-socket) добавлены две новые функции. `socketpair()` возвращает пару соединённых сокетов, а `getservbyport(port)` находит имя службы по номеру порта. (Авторы – Dave Cole и Barry Warsaw.)809- Функция `sys.exitfunc()` объявлена устаревшей. В коде следует использовать существующий модуль [`atexit`](https://python-all.ru/3.4/library/atexit.html#module-atexit), который корректно обрабатывает вызов нескольких функций завершения. Со временем `sys.exitfunc()` станет чисто внутренним интерфейсом, доступным только через [`atexit`](https://python-all.ru/3.4/library/atexit.html#module-atexit).810- Модуль [`tarfile`](https://python-all.ru/3.4/library/tarfile.html#module-tarfile) теперь по умолчанию создаёт tar-файлы в формате GNU. (Автор – Lars Gustäbel.)811- Модуль [`threading`](https://python-all.ru/3.4/library/threading.html#module-threading) теперь предлагает элегантно простой способ поддержки данных, локальных для потока. В модуле содержится класс `local`, значения атрибутов которого локальны для разных потоков.812813 ```python814 import threading815816 data = threading.local()817 data.number = 42818 data.url = ('www.python.org', 80)819 ```820821 Другие потоки могут присваивать и получать собственные значения для атрибутов `number` и `url`. От `local` можно создавать подклассы для инициализации атрибутов или добавления методов. (Автор – Jim Fulton.)822- Модуль [`timeit`](https://python-all.ru/3.4/library/timeit.html#module-timeit) теперь автоматически отключает периодическую сборку мусора во время цикла замера. Это изменение делает последовательные замеры более сопоставимыми. (Автор – Raymond Hettinger.)823- Модуль [`weakref`](https://python-all.ru/3.4/library/weakref.html#module-weakref) теперь поддерживает более широкий спектр объектов, включая функции Python, экземпляры классов, множества, неизменяемые множества (frozenset), двусторонние очереди (deque), массивы, файлы, сокеты и объекты шаблонов регулярных выражений. (Автор – Raymond Hettinger.)824- Модуль `xmlrpclib` теперь поддерживает расширение multi-call для передачи нескольких XML-RPC-вызовов в одной HTTP-операции. (Автор – Brian Quinlan.)825- Модули `mpz`, `rotor` и `xreadlines` удалены.826827### cookielib828829Библиотека `cookielib` поддерживает обработку HTTP-куки на стороне клиента, подобно тому, как модуль `Cookie` поддерживает куки на стороне сервера. Куки хранятся в хранилищах (cookie jar); библиотека прозрачно сохраняет куки, предлагаемые веб-сервером, в хранилище и извлекает их оттуда при подключении к серверу. Как и в веб-браузерах, объекты политики определяют, принимать ли куки.830831Для сохранения куки между сеансами предоставляются две реализации хранилищ: одна хранит куки в формате Netscape, чтобы приложения могли использовать файлы куки Mozilla или Lynx, а другая хранит куки в том же формате, что и библиотека Perl libwww.832833`urllib2` был изменён для взаимодействия с `cookielib`: `HTTPCookieProcessor` управляет хранилищем куки, которое используется при доступе к URL.834835Этот модуль был предоставлен Джоном Дж. Ли.836837### doctest838839Модуль [`doctest`](https://python-all.ru/3.4/library/doctest.html#module-doctest) претерпел значительный рефакторинг благодаря Эдварду Лоперу и Тиму Питерсу. Тестирование по-прежнему может быть таким же простым, как запуск [`doctest.testmod()`](https://python-all.ru/3.4/library/doctest.html#doctest.testmod), но рефакторинг позволяет настраивать работу модуля различными способами.840841Новый класс `DocTestFinder` извлекает тесты из docstrings заданного объекта:842843```python844def f (x, y):845 """>>> f(2,2)8464847>>> f(3,2)8486849 """850 return x*y851852finder = doctest.DocTestFinder()853854# получить список экземпляров DocTest855tests = finder.find(f)856```857858Затем новый класс `DocTestRunner` запускает отдельные тесты и может сформировать сводку результатов:859860```python861runner = doctest.DocTestRunner()862for t in tests:863 tried, failed = runner.run(t)864865runner.summarize(verbose=1)866```867868Приведённый выше пример даёт следующий вывод:869870```python8711 items passed all tests:872 2 tests in f8732 tests in 1 items.8742 passed and 0 failed.875Test passed.876```877878`DocTestRunner` использует экземпляр класса `OutputChecker` для сравнения ожидаемого вывода с фактическим. Этот класс принимает ряд различных флагов, настраивающих его поведение; опытные пользователи также могут написать полностью новый подкласс `OutputChecker`.879880Стандартная проверка вывода предоставляет ряд удобных возможностей. Например, с флагом опции [`doctest.ELLIPSIS`](https://python-all.ru/3.4/library/doctest.html#doctest.ELLIPSIS) многоточие (`...`) в ожидаемом выводе совпадает с любой подстрокой, что упрощает обработку выводов, которые незначительно различаются:881882```python883def o (n):884 """>>> o(1)885<__main__.C instance at 0x...>886>>>887"""888```889890Ещё одна специальная строка, `<BLANKLINE>`, соответствует пустой строке:891892```python893def p (n):894 """>>> p(1)895<BLANKLINE>896>>>897"""898```899900Ещё одна новая возможность – отображение вывода в стиле diff с помощью флагов опций [`doctest.REPORT_UDIFF`](https://python-all.ru/3.4/library/doctest.html#doctest.REPORT_UDIFF) (унифицированные diff), [`doctest.REPORT_CDIFF`](https://python-all.ru/3.4/library/doctest.html#doctest.REPORT_CDIFF) (контекстные diff) или [`doctest.REPORT_NDIFF`](https://python-all.ru/3.4/library/doctest.html#doctest.REPORT_NDIFF) (дельта-стиль). Например:901902```python903def g (n):904 """>>> g(4)905здесь906есть907a908длинный909>>>"""910 L = 'here is a rather lengthy list of words'.split()911 for word in L[:n]:912 print word913```914915При запуске тестов вышеуказанной функции с указанием [`doctest.REPORT_UDIFF`](https://python-all.ru/3.4/library/doctest.html#doctest.REPORT_UDIFF) получается следующий вывод:916917```python918**********************************************************************919File "t.py", line 15, in g920Failed example:921 g(4)922Differences (unified diff with -expected +actual):923 @@ -2,3 +2,3 @@924 is925 a926 -lengthy927 +rather928**********************************************************************929```930931## Изменения в сборке и C API932933Некоторые из изменений в процессе сборки Python и в C API:934935- Было добавлено три новых удобных макроса для распространённых возвращаемых значений из функций расширения: [`Py_RETURN_NONE`](https://python-all.ru/3.4/c-api/none.html#c.Py_RETURN_NONE), [`Py_RETURN_TRUE`](https://python-all.ru/3.4/c-api/bool.html#c.Py_RETURN_TRUE) и [`Py_RETURN_FALSE`](https://python-all.ru/3.4/c-api/bool.html#c.Py_RETURN_FALSE). (Автор: Brett Cannon.)936- Ещё один новый макрос, `Py_CLEAR(obj)`, уменьшает счётчик ссылок *obj* и устанавливает *obj* в нулевой указатель. (Автор: Jim Fulton.)937- Новая функция `PyTuple_Pack(N, obj1, obj2, ..., objN)` создаёт кортежи из списка аргументов переменной длины, состоящего из объектов Python. (Автор: Raymond Hettinger.)938- Новая функция `PyDict_Contains(d, k)` реализует быстрый поиск в словаре без скрытия исключений, возникающих в процессе поиска. (Автор: Raymond Hettinger.)939- Макрос `Py_IS_NAN(X)` возвращает 1, если его аргумент типа float или double *X* является NaN. (Автор: Tim Peters.)940- Код на C может избежать ненужной блокировки, используя новую функцию [`PyEval_ThreadsInitialized()`](https://python-all.ru/3.4/c-api/init.html#c.PyEval_ThreadsInitialized), чтобы определить, выполнялись ли какие-либо операции с потоками. Если эта функция возвращает false, операции блокировки не нужны. (Автор: Nick Coghlan.)941- Новая функция [`PyArg_VaParseTupleAndKeywords()`](https://python-all.ru/3.4/c-api/arg.html#c.PyArg_VaParseTupleAndKeywords) аналогична [`PyArg_ParseTupleAndKeywords()`](https://python-all.ru/3.4/c-api/arg.html#c.PyArg_ParseTupleAndKeywords), но принимает `va_list` вместо нескольких аргументов. (Автор: Greg Chapman.)942- Новый флаг метода `METH_COEXISTS` позволяет функции, определённой в слотах, сосуществовать с [`PyCFunction`](https://python-all.ru/3.4/c-api/structures.html#c.PyCFunction) с тем же именем. Это может вдвое сократить время доступа к методу, такому как `set.__contains__()`. (Автор: Raymond Hettinger.)943- Python теперь можно собрать с дополнительным профилированием самого интерпретатора, предназначенным в помощь разработчикам ядра Python. Передача *----enable-profiling* скрипту **configure** позволит профилировать интерпретатор с помощью **gprof**, а передача ключа *----with-tsc* включает профилирование с использованием регистра счётчика временных меток Pentium. Обратите внимание, что ключ *----with-tsc* назван не совсем точно, поскольку функция профилирования также работает на платформе PowerPC, хотя в этой архитектуре процессора этот регистр не называют «регистром TSC». (Автор: Jeremy Hylton.)944- Тип `tracebackobject` был переименован в `PyTracebackObject`.945946### Изменения, специфичные для платформ947948- Версия для Windows теперь собирается в MSVC++ 7.1, а также в версии 6. (Автор: Мартин фон Лёвис.)949950## Переход на Python 2.4951952В этом разделе перечислены описанные ранее изменения, которые могут потребовать изменения кода:953954- Сдвиги влево и шестнадцатеричные/восьмеричные константы, которые слишком велики, больше не вызывают [`FutureWarning`](https://python-all.ru/3.4/library/exceptions.html#FutureWarning) и не возвращают значение, ограниченное 32 или 64 битами; вместо этого они возвращают длинное целое.955- Целочисленные операции больше не будут вызывать предупреждение `OverflowWarning`. Предупреждение `OverflowWarning` исчезнет в Python 2.5.956- Встроенная функция [`zip()`](https://python-all.ru/3.4/library/functions.html#zip) и `itertools.izip()` теперь возвращают пустой список вместо возбуждения исключения [`TypeError`](https://python-all.ru/3.4/library/exceptions.html#TypeError), если вызваны без аргументов.957- Больше нельзя сравнивать экземпляры `date` и [`datetime`](https://python-all.ru/3.4/library/datetime.html#module-datetime) из модуля [`datetime`](https://python-all.ru/3.4/library/datetime.html#module-datetime). Два экземпляра разных классов теперь всегда будут неравны, а операции относительного сравнения (`<`, `>`) будут возбуждать [`TypeError`](https://python-all.ru/3.4/library/exceptions.html#TypeError).958- `dircache.listdir()` теперь передаёт исключения вызывающему коду вместо возврата пустых списков.959- `LexicalHandler.startDTD()` раньше получал общедоступный и системный идентификаторы в неправильном порядке. Это было исправлено; приложения, полагающиеся на неправильный порядок, необходимо исправить.960- [`fcntl.ioctl()`](https://python-all.ru/3.4/library/fcntl.html#fcntl.ioctl) теперь выдаёт предупреждение, если аргумент *mutate* опущен и это актуально.961- Модуль [`tarfile`](https://python-all.ru/3.4/library/tarfile.html#module-tarfile) теперь по умолчанию создаёт tar-файлы в формате GNU.962- При ошибке во время импорта модуля в `sys.modules` больше не остаётся частично инициализированный объект модуля.963- [`None`](https://python-all.ru/3.4/library/constants.html#None) теперь является константой; код, который присваивает новое значение имени `None`, теперь вызывает синтаксическую ошибку.964- Функция `signals.signal()` теперь возбуждает исключение [`RuntimeError`](https://python-all.ru/3.4/library/exceptions.html#RuntimeError) для некоторых недопустимых значений; ранее эти ошибки проходили незаметно. Например, больше нельзя установить обработчик на сигнал `SIGKILL`.965966## Благодарности967968Автор хотел бы поблагодарить следующих людей за предложения, исправления и помощь в работе над различными черновиками этой статьи: Koray Can, Hye-Shik Chang, Michael Dyck, Raymond Hettinger, Brian Hurt, Hamish Lawson, Fredrik Lundh, Sean Reifschneider, Sadruddin Rejeb.969