2.2.md
1> **Источник:** https://python-all.ru/3.5/whatsnew/2.2.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# Что нового в Python 2.289| Автор: | A.M. Kuchling |10| --- | --- |1112## Введение1314Эта статья объясняет новые возможности Python 2.2.2, выпущенного 14 октября 2002 года. Python 2.2.2 – это выпуск с исправлением ошибок Python 2.2, первоначально вышедшего 21 декабря 2001 года.1516Python 2.2 можно считать «релизом по наведению порядка». В нём есть несколько совершенно новых возможностей, таких как генераторы и итераторы, но большинство изменений, какими бы значительными и далеко идущими они ни были, направлены на устранение непоследовательностей и тёмных углов в дизайне языка.1718Эта статья не претендует на полноценную спецификацию новых возможностей, а даёт удобный обзор. За полными подробностями обращайтесь к документации Python 2.2, например, к [Справочнику по библиотеке Python](https://python-all.ru/3.5/whatsnew/2.2.html) и [Справочному руководству Python](https://python-all.ru/3.5/whatsnew/2.2.html). Если вы хотите понять полную реализацию и обоснование дизайна какого-либо изменения, обратитесь к соответствующему PEP для этой новой возможности.1920## PEP 252 и 253: Изменения типов и классов2122Самые большие и далеко идущие изменения в Python 2.2 касаются модели объектов и классов. Изменения должны быть обратно совместимы, поэтому ваш код, скорее всего, продолжит работать без изменений, но эти изменения дают потрясающие новые возможности. Перед тем как приступить к самому длинному и сложному разделу этой статьи, я дам обзор изменений и выскажу несколько замечаний.2324Давным-давно я написал веб-страницу с перечнем недостатков дизайна Python. Одним из самых значительных недостатков была невозможность наследования от типов Python, реализованных на C. В частности, невозможно наследовать от встроенных типов, поэтому нельзя просто взять и унаследовать, скажем, список, чтобы добавить к нему один полезный метод. Модуль `UserList` предоставляет класс, который поддерживает все методы списков и от которого можно наследовать, но существует много кода на C, который ожидает обычный список Python и не примет экземпляр `UserList`.2526Python 2.2 исправляет это, и в процессе добавляет несколько захватывающих новых возможностей. Краткое резюме:2728- Вы можете наследовать встроенные типы, такие как списки и даже целые числа, и ваши подклассы должны работать везде, где требуется исходный тип.29- Теперь можно определять статические методы и методы класса, в дополнение к методам экземпляра, доступным в предыдущих версиях Python.30- Также можно автоматически вызывать методы при доступе к атрибуту экземпляра или его установке, используя новый механизм, называемый *свойствами*. Многие случаи использования [`__getattr__()`](https://python-all.ru/3.5/reference/datamodel.html#object.__getattr__) можно переписать на свойства, что сделает код проще и быстрее. В качестве небольшого побочного преимущества, атрибуты теперь могут иметь докстринги.31- Список допустимых атрибутов экземпляра можно ограничить определённым набором с помощью *слотов*, что позволяет защититься от опечаток и, возможно, сделать больше оптимизаций в будущих версиях Python.3233Некоторые пользователи выразили обеспокоенность по поводу всех этих изменений. «Конечно, – говорят они, – новые функции интересны и позволяют делать разные трюки, которые были невозможны в предыдущих версиях Python, но они также усложняют язык». Некоторые говорят, что всегда рекомендовали Python за его простоту, и чувствуют, что эта простота теряется.3435Лично я считаю, что беспокоиться не о чем. Многие новые возможности довольно эзотеричны, и вы можете писать много кода на Python, даже не подозревая о них. Написание простого класса не сложнее, чем раньше, так что вам не нужно утруждать себя их изучением или обучением, если они действительно не нужны. Некоторые очень сложные задачи, которые ранее были возможны только на C, теперь можно решать на чистом Python, и, на мой взгляд, это только к лучшему.3637Я не буду пытаться охватить каждый частный случай и мелкое изменение, необходимые для работы новых функций. Вместо этого данный раздел опишет только общую картину. Смотрите раздел [Связанные ссылки](https://python-all.ru/3.5/whatsnew/2.2.html#sect-rellinks), «Связанные ссылки», для получения дополнительных источников информации о новой объектной модели Python 2.2.3839### Старые и новые классы4041Прежде всего, следует знать, что Python 2.2 действительно имеет два вида классов: классические (или старые) классы и классы нового стиля. Модель старых классов в точности такая же, как в более ранних версиях Python. Все новые возможности, описанные в этом разделе, применимы только к классам нового стиля. Это разделение не предполагается сохранять навсегда; в конечном итоге старые классы будут удалены, возможно, в Python 3.0.4243Итак, как определить класс нового стиля? Для этого нужно унаследоваться от существующего класса нового стиля. Большинство встроенных типов Python, такие как целые числа, списки, словари и даже файлы, теперь являются классами нового стиля. Также был добавлен класс нового стиля с именем [`object`](https://python-all.ru/3.5/library/functions.html#object), базовый класс для всех встроенных типов, так что если ни один встроенный тип не подходит, можно просто унаследоваться от [`object`](https://python-all.ru/3.5/library/functions.html#object):4445```python46class C(object):47 def __init__ (self):48 ...49 ...50```5152Это означает, что операторы [`class`](https://python-all.ru/3.5/reference/compound_stmts.html#class), не имеющие базовых классов, в Python 2.2 всегда являются классическими классами. (На самом деле это можно изменить, установив переменную уровня модуля с именем `__metaclass__` – подробности см. в [**PEP 253**](https://python-all.ru/3.5/whatsnew/2.2.html) – но проще просто унаследоваться от [`object`](https://python-all.ru/3.5/c-api/object.html#object).)5354Объекты типов для встроенных типов доступны как встроенные объекты, названные с помощью хитроумного трюка. В Python всегда были встроенные функции [`int()`](https://python-all.ru/3.5/library/functions.html#int), [`float()`](https://python-all.ru/3.5/library/functions.html#float) и [`str()`](https://python-all.ru/3.5/library/stdtypes.html#str). В версии 2.2 они больше не являются функциями, а представляют собой объекты типов, которые ведут себя как фабрики при вызове.5556```python57>>> int58<type 'int'>59>>> int('123')6012361```6263Для полноты набора типов были добавлены новые объекты типов, такие как [`dict()`](https://python-all.ru/3.5/library/stdtypes.html#dict) и `file()`. Вот более интересный пример: добавление метода `lock()` к файловым объектам:6465```python66class LockableFile(file):67 def lock (self, operation, length=0, start=0, whence=0):68 import fcntl69 return fcntl.lockf(self.fileno(), operation,70 length, start, whence)71```7273Сейчас устаревший модуль `posixfile` содержал класс, который эмулировал все методы файлового объекта и также добавлял метод `lock()`, но этот класс нельзя было передать внутренним функциям, ожидающим встроенный файл, что теперь возможно с нашим новым `LockableFile`.7475### Дескрипторы7677В предыдущих версиях Python не было единого способа узнать, какие атрибуты и методы поддерживаются объектом. Существовали неформальные соглашения, такие как определение атрибутов `__members__` и `__methods__`, содержащих списки имён, но часто автор расширения или класса не утруждал себя их определением. Можно было прибегнуть к проверке [`__dict__`](https://python-all.ru/3.5/library/stdtypes.html#object.__dict__) объекта, но при использовании наследования классов или произвольного хука [`__getattr__()`](https://python-all.ru/3.5/reference/datamodel.html#object.__getattr__) это могло быть неточным.7879Одна большая идея, лежащая в основе новой модели классов, заключается в формализации API для описания атрибутов объекта с помощью *дескрипторов*. Дескрипторы определяют значение атрибута, указывая, является ли он методом или полем. Благодаря API дескрипторов становятся возможными статические методы, методы класса, а также более экзотические конструкции.8081Дескрипторы атрибутов – это объекты, которые находятся внутри объектов классов и имеют несколько собственных атрибутов:8283- [`__name__`](https://python-all.ru/3.5/library/stdtypes.html#definition.__name__) – это имя атрибута.84- `__doc__` – это докстринг атрибута.85- `__get__(object)` – это метод, который извлекает значение атрибута из *объекта*.86- `__set__(object, value)` устанавливает атрибут *объекта* в *значение*.87- `__delete__(object, value)` удаляет атрибут *значение* объекта *объекта*.8889Например, при записи `obj.x` Python выполняет следующие шаги:9091```python92descriptor = obj.__class__.x93descriptor.__get__(obj)94```9596Для методов, `descriptor.__get__()` возвращает временный объект, который можно вызывать, и упаковывает экземпляр и метод, который должен быть вызван на нём. Именно поэтому теперь возможны статические методы и методы класса; у них есть дескрипторы, которые упаковывают только метод, или метод и класс. Краткое объяснение этих новых видов методов: статическим методам не передаётся экземпляр, поэтому они похожи на обычные функции. Методам класса передаётся класс объекта, но не сам объект. Статические методы и методы класса определяются так:9798```python99class C(object):100 def f(arg1, arg2):101 ...102 f = staticmethod(f)103104 def g(cls, arg1, arg2):105 ...106 g = classmethod(g)107```108109Функция [`staticmethod()`](https://python-all.ru/3.5/library/functions.html#staticmethod) принимает функцию `f()` и возвращает её, упакованную в дескриптор, чтобы её можно было сохранить в объекте класса. Можно было бы ожидать специального синтаксиса для создания таких методов (`def static f`, `defstatic f()` или чего-то подобного), но такого синтаксиса пока не определено; это оставлено для будущих версий Python.110111Многие новые возможности, такие как слоты (slots) и свойства (properties), также реализованы как новые виды дескрипторов, и написать класс дескриптора, делающий что-то новое, несложно. Например, можно написать класс дескриптора, который позволяет записывать предусловия и постусловия в стиле языка Eiffel для метода. Класс, использующий эту возможность, может быть определён следующим образом:112113```python114from eiffel import eiffelmethod115116class C(object):117 def f(self, arg1, arg2):118 # Собственно функция119 ...120 def pre_f(self):121 # Проверить предусловия122 ...123 def post_f(self):124 # Проверить постусловия125 ...126127 f = eiffelmethod(f, pre_f, post_f)128```129130Обратите внимание, что человеку, использующему новые `eiffelmethod()`, не нужно ничего понимать в дескрипторах. Поэтому я считаю, что новые возможности не увеличивают базовую сложность языка. Найдётся несколько волшебников, которым нужно знать о них, чтобы написать `eiffelmethod()` или ZODB, или что-то ещё, но большинство пользователей просто будут писать код поверх получившихся библиотек и игнорировать детали реализации.131132### Множественное наследование: правило ромба133134Множественное наследование стало более полезным благодаря изменению правил разрешения имён. Рассмотрим следующий набор классов (диаграмма взята из [**PEP 253**](https://python-all.ru/3.5/whatsnew/2.2.html) Гвидо ван Россума):135136```python137 class A:138 ^ ^ def save(self): ...139 / \140 / \141 / \142 / \143class B class C:144 ^ ^ def save(self): ...145 \ /146 \ /147 \ /148 \ /149 class D150```151152Правило поиска для классических классов простое, но не очень умное: базовые классы просматриваются в глубину, слева направо. Обращение к `D.save()` будет искать в классах `D`, `B`, а затем `A`, где будет найден `save()` и возвращён. `C.save()` не будет найден вообще. Это плохо, потому что если метод `save()` `C` сохраняет некоторое внутреннее состояние, специфичное для `C`, то его невызов приведёт к тому, что это состояние никогда не будет сохранено.153154Классы нового стиля следуют другому алгоритму, который немного сложнее объяснить, но делает правильное дело в этой ситуации. (Обратите внимание, что Python 2.3 изменяет этот алгоритм на тот, который в большинстве случаев даёт те же результаты, но даёт более полезные результаты для действительно сложных графов наследования.)1551561. Перечислить все базовые классы, следуя классическому правилу поиска, и включать класс несколько раз, если он посещается повторно. В приведённом примере список посещённых классов: \[`D`, `B`, `A`, `C`, `A`\].1572. Проверить список на наличие дублирующихся классов. Если таковые найдены, удалить все вхождения, кроме одного, оставив *последнее* в списке. В приведённом примере список становится \[`D`, `B`, `C`, `A`\] после удаления дубликатов.158159Следуя этому правилу, обращение к `D.save()` вернёт `C.save()`, что и является нужным поведением. Это правило поиска совпадает с правилом, используемым в Common Lisp. Новая встроенная функция [`super()`](https://python-all.ru/3.5/library/functions.html#super) предоставляет способ получить суперклассы класса без необходимости повторной реализации алгоритма Python. Наиболее часто используемой формой будет `super(class, obj)`, которая возвращает связанный объект суперкласса (не сам объект класса). Эта форма будет использоваться в методах для вызова метода суперкласса; например, метод `save()` `D` будет выглядеть следующим образом:160161```python162class D (B,C):163 def save (self):164 # Вызвать .save() родительского класса165 super(D, self).save()166 # Сохранить приватные данные D здесь167 ...168```169170[`super()`](https://python-all.ru/3.5/library/functions.html#super) также может возвращать несвязанные объекты суперкласса при вызове как `super(class)` или `super(class1, class2)`, но это, вероятно, не будет часто полезно.171172### Доступ к атрибутам173174Немало сложных классов Python определяют перехватчики для доступа к атрибутам с помощью [`__getattr__()`](https://python-all.ru/3.5/reference/datamodel.html#object.__getattr__); чаще всего это делается для удобства, чтобы сделать код более читаемым за счёт автоматического преобразования доступа к атрибуту, такого как `obj.parent`, в вызов метода, такой как `obj.get_parent`. Python 2.2 добавляет несколько новых способов управления доступом к атрибутам.175176Во-первых, `__getattr__(attr_name)` по-прежнему поддерживается классами нового стиля, и в нём ничего не изменилось. Как и прежде, он будет вызываться при попытке доступа к `obj.foo`, если в словаре экземпляра не найден атрибут с именем `foo`.177178Классы нового стиля также поддерживают новый метод – `__getattribute__(attr_name)`. Разница между двумя методами в том, что [`__getattribute__()`](https://python-all.ru/3.5/reference/datamodel.html#object.__getattribute__) вызывается *всегда* при любом доступе к атрибуту, тогда как старый [`__getattr__()`](https://python-all.ru/3.5/reference/datamodel.html#object.__getattr__) вызывается только если `foo` не найден в словаре экземпляра.179180Однако поддержка *свойств (properties)* в Python 2.2 часто будет более простым способом перехвата обращений к атрибутам. Написание метода [`__getattr__()`](https://python-all.ru/3.5/reference/datamodel.html#object.__getattr__) – дело сложное, потому что для избежания рекурсии внутри него нельзя использовать обычные обращения к атрибутам, и вместо этого приходится работать с содержимым [`__dict__`](https://python-all.ru/3.5/library/stdtypes.html#object.__dict__). Методы [`__getattr__()`](https://python-all.ru/3.5/reference/datamodel.html#object.__getattr__) также вызываются Python при проверке других методов, таких как [`__repr__()`](https://python-all.ru/3.5/reference/datamodel.html#object.__repr__) или `__coerce__()`, поэтому их нужно писать с учётом этого. Наконец, вызов функции при каждом доступе к атрибуту приводит к существенному снижению производительности.181182[`property`](https://python-all.ru/3.5/library/functions.html#property) – это новый встроенный тип, который объединяет три функции: получения, установки или удаления атрибута, а также строку документации. Например, если требуется определить атрибут `size`, который вычисляется, но также может быть установлен, можно написать:183184```python185class C(object):186 def get_size (self):187 result = ... computation ...188 return result189 def set_size (self, size):190 ... compute something based on the size191 and set internal state appropriately ...192193 # Определить свойство. Метод 'delete this attribute'194 # метод определён как None, поэтому атрибут195 # не может быть удалён.196 size = property(get_size, set_size,197 None,198 "Storage size of this instance")199```200201Это, безусловно, понятнее и проще в написании, чем пара методов [`__getattr__()`](https://python-all.ru/3.5/reference/datamodel.html#object.__getattr__)/[`__setattr__()`](https://python-all.ru/3.5/reference/datamodel.html#object.__setattr__), которые проверяют атрибут `size` и обрабатывают его особым образом, извлекая все остальные атрибуты из [`__dict__`](https://python-all.ru/3.5/library/stdtypes.html#object.__dict__) экземпляра. Кроме того, доступ к `size` – единственный, который требует вызова функции, поэтому обращения к другим атрибутам выполняются на обычной скорости.202203Наконец, можно ограничить список атрибутов, к которым можно обращаться у объекта, с помощью нового атрибута класса [`__slots__`](https://python-all.ru/3.5/reference/datamodel.html#object.__slots__). Объекты Python обычно очень динамичны; в любой момент можно определить новый атрибут у экземпляра, просто написав `obj.new_attr=1`. Класс нового стиля может определить атрибут класса с именем [`__slots__`](https://python-all.ru/3.5/reference/datamodel.html#object.__slots__), чтобы ограничить допустимые атрибуты определённым набором имён. Пример прояснит это:204205```python206>>> class C(object):207... __slots__ = ('template', 'name')208...209>>> obj = C()210>>> print obj.template211None212>>> obj.template = 'Test'213>>> print obj.template214Test215>>> obj.newattr = None216Traceback (most recent call last):217 File "<stdin>", line 1, in ?218AttributeError: 'C' object has no attribute 'newattr'219```220221Обратите внимание, что при попытке присвоить значение атрибуту, не указанному в [`__slots__`](https://python-all.ru/3.5/reference/datamodel.html#object.__slots__), возникает [`AttributeError`](https://python-all.ru/3.5/library/exceptions.html#AttributeError).222223### Связанные ссылки224225Этот раздел был лишь кратким обзором новых возможностей, дающим достаточно объяснений, чтобы начать программировать, но многие детали были упрощены или опущены. Куда обратиться, чтобы получить более полную картину?226227[https://docs.python.org/dev/howto/descriptor.html](https://python-all.ru/3.5/dev/howto/descriptor.html) – это подробное учебное введение в дескрипторы, написанное Гвидо ван Россумом. Если моё описание разожгло ваш аппетит, прочитайте это руководство следующим, так как оно вдаётся в гораздо более подробные детали о новых возможностях, оставаясь при этом достаточно лёгким для чтения.228229Далее есть два соответствующих PEP: [**PEP 252**](https://python-all.ru/3.5/whatsnew/2.2.html) и [**PEP 253**](https://python-all.ru/3.5/whatsnew/2.2.html). [**PEP 252**](https://python-all.ru/3.5/whatsnew/2.2.html) называется «Making Types Look More Like Classes» и описывает API дескрипторов. [**PEP 253**](https://python-all.ru/3.5/whatsnew/2.2.html) называется «Subtyping Built-in Types» и описывает изменения в объектах типов, которые делают возможным создание подтипов встроенных объектов. [**PEP 253**](https://python-all.ru/3.5/whatsnew/2.2.html) – более сложный из двух PEP, и в некоторых местах необходимые объяснения типов и метатипов могут вызвать головную боль. Оба PEP были написаны и реализованы Гвидо ван Россумом при значительной помощи остальной команды Zope Corp.230231Наконец, есть высший авторитет: исходный код. Большая часть механизмов обработки типов находится в `Objects/typeobject.c`, но обращаться к нему следует только после того, как исчерпаны все другие возможности, включая отправку вопроса в python-list или python-dev.232233## PEP 234: Итераторы234235Ещё одно значительное дополнение в 2.2 – это интерфейс итерации на уровнях C и Python. Объекты могут определять, как по ним можно итерироваться вызывающим кодом.236237В версиях Python до 2.1 обычным способом заставить `for item in obj` работать было определение метода [`__getitem__()`](https://python-all.ru/3.5/reference/datamodel.html#object.__getitem__), который выглядел примерно так:238239```python240def __getitem__(self, index):241 return <next item>242```243244[`__getitem__()`](https://python-all.ru/3.5/reference/datamodel.html#object.__getitem__) правильнее использовать для определения операции индексирования объекта, чтобы можно было писать `obj[5]` для получения шестого элемента. Это немного сбивает с толку, когда вы используете это только для поддержки циклов [`for`](https://python-all.ru/3.5/reference/compound_stmts.html#for). Рассмотрим некий файлоподобный объект, по которому нужно итерироваться; параметр *index* по сути бессмысленен, так как класс, вероятно, предполагает, что будет сделана серия вызовов [`__getitem__()`](https://python-all.ru/3.5/reference/datamodel.html#object.__getitem__) с увеличивающимся на единицу *index*. Другими словами, наличие метода [`__getitem__()`](https://python-all.ru/3.5/reference/datamodel.html#object.__getitem__) не означает, что использование `file[5]` для произвольного доступа к шестому элементу сработает, хотя на самом деле должно.245246В Python 2.2 итерацию можно реализовать отдельно, а методы [`__getitem__()`](https://python-all.ru/3.5/reference/datamodel.html#object.__getitem__) можно ограничить классами, которые действительно поддерживают произвольный доступ. Основная идея итераторов проста. Новая встроенная функция `iter(obj)` или `iter(C, sentinel)` используется для получения итератора. `iter(obj)` возвращает итератор для объекта *obj*, а `iter(C, sentinel)` возвращает итератор, который будет вызывать вызываемый объект *C* до тех пор, пока он не вернёт *sentinel*, сигнализируя об окончании итератора.247248Классы Python могут определять метод [`__iter__()`](https://python-all.ru/3.5/reference/datamodel.html#object.__iter__), который должен создавать и возвращать новый итератор для объекта; если объект сам является своим итератором, этот метод может просто вернуть `self`. В частности, итераторы обычно являются собственными итераторами. Расширения, реализованные на C, могут реализовать функцию [`tp_iter`](https://python-all.ru/3.5/c-api/typeobj.html#c.PyTypeObject.tp_iter) для возврата итератора, а расширения, которые хотят вести себя как итераторы, могут определить функцию [`tp_iternext`](https://python-all.ru/3.5/c-api/typeobj.html#c.PyTypeObject.tp_iternext).249250Итак, что же на самом деле делают итераторы? У них есть один обязательный метод [`next()`](https://python-all.ru/3.5/library/functions.html#next), который не принимает аргументов и возвращает следующее значение. Когда больше нечего возвращать, вызов [`next()`](https://python-all.ru/3.5/library/functions.html#next) должен возбуждать исключение [`StopIteration`](https://python-all.ru/3.5/library/exceptions.html#StopIteration).251252```python253>>> L = [1,2,3]254>>> i = iter(L)255>>> print i256<iterator object at 0x8116870>257>>> i.next()2581259>>> i.next()2602261>>> i.next()2623263>>> i.next()264Traceback (most recent call last):265 File "<stdin>", line 1, in ?266StopIteration267>>>268```269270В Python 2.2 оператор [`for`](https://python-all.ru/3.5/reference/compound_stmts.html#for) больше не требует последовательности; он ожидает объект, для которого [`iter()`](https://python-all.ru/3.5/library/functions.html#iter) вернёт итератор. Для обратной совместимости и удобства итератор автоматически создаётся для последовательностей, которые не реализуют [`__iter__()`](https://python-all.ru/3.5/reference/datamodel.html#object.__iter__) или слот [`tp_iter`](https://python-all.ru/3.5/c-api/typeobj.html#c.PyTypeObject.tp_iter), так что `for i in [1,2,3]` по-прежнему будет работать. Везде, где интерпретатор Python выполняет цикл по последовательности, он теперь использует протокол итератора. Это означает, что можно делать, например, следующее:271272```python273>>> L = [1,2,3]274>>> i = iter(L)275>>> a,b,c = i276>>> a,b,c277(1, 2, 3)278```279280Поддержка итераторов была добавлена для некоторых базовых типов Python. Вызов [`iter()`](https://python-all.ru/3.5/library/functions.html#iter) для словаря вернёт итератор, который перебирает его ключи:281282```python283>>> m = {'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6,284... 'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12}285>>> for key in m: print key, m[key]286...287Mar 3288Feb 2289Aug 8290Sep 9291May 5292Jun 6293Jul 7294Jan 1295Apr 4296Nov 11297Dec 12298Oct 10299```300301Это поведение по умолчанию. Если нужно перебрать ключи, значения или пары ключ/значение, можно явно вызвать методы `iterkeys()`, `itervalues()` или `iteritems()`, чтобы получить соответствующий итератор. В связанном небольшом изменении оператор [`in`](https://python-all.ru/3.5/reference/expressions.html#in) теперь работает со словарями, так что `key in dict` теперь эквивалентно `dict.has_key(key)`.302303Файлы также предоставляют итератор, который вызывает метод [`readline()`](https://python-all.ru/3.5/library/readline.html#module-readline), пока в файле есть строки. Это означает, что теперь можно читать каждую строку файла с помощью такого кода:304305```python306for line in file:307 # сделать что-то для каждой строки308 ...309```310311Обратите внимание, что итератор можно перемещать только вперёд; нет способа получить предыдущий элемент, сбросить итератор или сделать его копию. Объект-итератор может предоставлять такие дополнительные возможности, но протокол итератора требует только метод [`next()`](https://python-all.ru/3.5/library/functions.html#next).312313> **См. также**314>315> **[**PEP 234**](https://python-all.ru/3.5/whatsnew/2.2.html) – Итераторы**316>317> Авторы: Ка-Пинг Йи и Гвидо ван Россум; реализовано командой Python Labs, в основном Гвидо и Тимом Петерсом.318319## PEP 255: Простые генераторы320321Генераторы – ещё одна новая возможность, которая связана с введением итераторов.322323Вы, несомненно, знакомы с тем, как работают вызовы функций в Python или C. Когда вызывается функция, она получает отдельное пространство имён, в котором создаются её локальные переменные. Когда функция достигает оператора [`return`](https://python-all.ru/3.5/reference/simple_stmts.html#return), локальные переменные уничтожаются, а полученное значение возвращается вызывающему. Последующий вызов той же функции получит новый набор локальных переменных. Но что, если бы локальные переменные не уничтожались при выходе из функции? Что, если бы можно было возобновить выполнение функции с того места, где она остановилась? Это и обеспечивают генераторы; их можно рассматривать как возобновляемые функции.324325Вот простейший пример функции-генератора:326327```python328def generate_ints(N):329 for i in range(N):330 yield i331```332333Для генераторов было введено новое ключевое слово [`yield`](https://python-all.ru/3.5/reference/simple_stmts.html#yield). Любая функция, содержащая оператор [`yield`](https://python-all.ru/3.5/reference/simple_stmts.html#yield), является генераторной функцией; это обнаруживается байт-код-компилятором Python, который компилирует такую функцию особым образом. Поскольку было введено новое ключевое слово, генераторы должны быть явно включены в модуле с помощью оператора `from __future__ import generators` в начале исходного кода модуля. В Python 2.3 этот оператор станет ненужным.334335Когда вы вызываете генераторную функцию, она не возвращает одно значение; вместо этого она возвращает объект-генератор, поддерживающий протокол итератора. При выполнении оператора [`yield`](https://python-all.ru/3.5/reference/simple_stmts.html#yield) генератор выводит значение `i`, аналогично оператору [`return`](https://python-all.ru/3.5/reference/simple_stmts.html#return). Основное различие между [`yield`](https://python-all.ru/3.5/reference/simple_stmts.html#yield) и оператором [`return`](https://python-all.ru/3.5/reference/simple_stmts.html#return) заключается в том, что при достижении [`yield`](https://python-all.ru/3.5/reference/simple_stmts.html#yield) состояние выполнения генератора приостанавливается, а локальные переменные сохраняются. При следующем вызове метода `next()` генератора функция возобновляет выполнение сразу после [`yield`](https://python-all.ru/3.5/reference/simple_stmts.html#yield) оператора. (По сложным причинам оператор [`yield`](https://python-all.ru/3.5/reference/simple_stmts.html#yield) не допускается внутри блока [`try`](https://python-all.ru/3.5/reference/compound_stmts.html#try) оператора [`try`](https://python-all.ru/3.5/reference/compound_stmts.html#try)…[`finally`](https://python-all.ru/3.5/reference/compound_stmts.html#finally); прочтите [**PEP 255**](https://python-all.ru/3.5/whatsnew/2.2.html) для полного объяснения взаимодействия между [`yield`](https://python-all.ru/3.5/reference/simple_stmts.html#yield) и исключениями.)336337Вот пример использования генератора `generate_ints()`:338339```python340>>> gen = generate_ints(3)341>>> gen342<generator object at 0x8117f90>343>>> gen.next()3440345>>> gen.next()3461347>>> gen.next()3482349>>> gen.next()350Traceback (most recent call last):351 File "<stdin>", line 1, in ?352 File "<stdin>", line 2, in generate_ints353StopIteration354```355356Можно также написать `for i in generate_ints(5)` или `a,b,c = generate_ints(3)`.357358Внутри генераторной функции оператор [`return`](https://python-all.ru/3.5/reference/simple_stmts.html#return) может использоваться только без значения и сигнализирует об окончании последовательности значений; после этого генератор не может вернуть никаких дополнительных значений. [`return`](https://python-all.ru/3.5/reference/simple_stmts.html#return) со значением, например `return 5`, является синтаксической ошибкой внутри генераторной функции. Конец результатов генератора также можно указать вручную, возбудив [`StopIteration`](https://python-all.ru/3.5/library/exceptions.html#StopIteration), или просто позволив потоку выполнения дойти до конца функции.359360Эффекта генераторов можно добиться вручную, написав собственный класс и сохранив все локальные переменные генератора как переменные экземпляра. Например, возврат списка целых чисел можно было бы реализовать, установив `self.count` в 0 и заставив метод [`next()`](https://python-all.ru/3.5/library/functions.html#next) увеличивать `self.count` и возвращать его. Однако для сколь-нибудь сложного генератора написание соответствующего класса было бы гораздо более запутанным. `Lib/test/test_generators.py` содержит ряд более интересных примеров. Самый простой из них реализует симметричный обход дерева с помощью рекурсивных генераторов.361362```python363# Рекурсивный генератор, порождающий листья дерева в порядке in-order.364def inorder(t):365 if t:366 for x in inorder(t.left):367 yield x368 yield t.label369 for x in inorder(t.right):370 yield x371```372373Два других примера в `Lib/test/test_generators.py` дают решения задачи о N ферзях (размещение N ферзей на шахматной доске N×N так, чтобы ни один ферзь не угрожал другому) и задачи об обходе коня (маршрут, по которому конь посещает каждую клетку доски N×N, не посещая ни одну клетку дважды).374375Идея генераторов пришла из других языков программирования, особенно Icon ([https://www.cs.arizona.edu/icon/](https://python-all.ru/3.5/whatsnew/2.2.html)), где идея генераторов является центральной. В Icon каждое выражение и вызов функции ведут себя как генератор. Один пример из «An Overview of the Icon Programming Language» по адресу [https://www.cs.arizona.edu/icon/docs/ipd266.htm](https://python-all.ru/3.5/whatsnew/2.2.html) даёт представление о том, как это выглядит:376377```python378sentence := "Store it in the neighboring harbor"379if (i := find("or", sentence)) > 5 then write(i)380```381382В Icon функция `find()` возвращает индексы, по которым найдена подстрока «or»: 3, 23, 33. В операторе [`if`](https://python-all.ru/3.5/reference/compound_stmts.html#if) переменной `i` сначала присваивается значение 3, но 3 меньше 5, поэтому сравнение не удаётся, и Icon повторяет попытку со вторым значением 23. 23 больше 5, поэтому теперь сравнение успешно, и код выводит на экран значение 23.383384Python не заходит так далеко, как Icon, в принятии генераторов в качестве центральной концепции. Генераторы считаются новой частью ядра языка Python, но их изучение или использование не является обязательным; если они не решают ваших задач, можете их игнорировать. Одной из новых особенностей интерфейса Python по сравнению с Icon является то, что состояние генератора представляется как конкретный объект (итератор), который можно передавать другим функциям или хранить в структуре данных.385386> **См. также**387>388> **[**PEP 255**](https://python-all.ru/3.5/whatsnew/2.2.html) - Simple Generators**389>390> Авторы: Нил Шеменауэр, Тим Питерс, Магнус Ли Хетланд. Реализовано в основном Нилом Шеменауэром и Тимом Питерсом, с дополнительными исправлениями от команды Python Labs.391392## PEP 237: Унификация длинных целых и целых чисел393394В последних версиях различие между обычными целыми (32-битными на большинстве машин) и длинными целыми (произвольного размера) стало раздражать. Например, на платформах, поддерживающих файлы размером более `2**32` байт, метод `tell()` файловых объектов должен возвращать длинное целое. Однако некоторые части Python ожидали обычные целые и выдавали ошибку, если вместо них передавалось длинное целое. Например, в Python 1.5 в качестве индекса среза можно было использовать только обычные целые, и `'abc'[1L:]` вызывало исключение [`TypeError`](https://python-all.ru/3.5/library/exceptions.html#TypeError) с сообщением 'slice index must be int'.395396Python 2.2 будет автоматически преобразовывать короткие целые в длинные по мере необходимости. Суффикс «L» больше не нужен для обозначения литерала длинного целого, так как компилятор теперь сам выбирает подходящий тип. (Использование суффикса «L» будет не рекомендоваться в будущих версиях Python 2.x, вызывая предупреждение в Python 2.4, и, вероятно, удалено в Python 3.0.) Многие операции, которые раньше вызывали [`OverflowError`](https://python-all.ru/3.5/library/exceptions.html#OverflowError), теперь будут возвращать длинное целое. Например:397398```python399>>> 12345678901234001234567890123L401>>> 2 ** 6440218446744073709551616L403```404405В большинстве случаев целые и длинные целые теперь обрабатываются одинаково. Вы всё ещё можете различать их с помощью встроенной функции [`type()`](https://python-all.ru/3.5/library/functions.html#type), но это редко требуется.406407> **См. также**408>409> **[**PEP 237**](https://python-all.ru/3.5/whatsnew/2.2.html) – Унификация длинных целых и целых чисел**410>411> Авторы: Моше Задка и Гвидо ван Россум. В основном реализовано Гвидо ван Россумом.412413## PEP 238: Изменение оператора деления414415Самое противоречивое изменение в Python 2.2 знаменует начало усилий по исправлению старого проектного недостатка, существовавшего в Python с самого начала. В настоящее время оператор деления Python, `/`, ведёт себя как оператор деления в C, когда оба операнда целые: он возвращает целочисленный результат, усечённый вниз при наличии дробной части. Например, `3/2` равно 1, а не 1,5, и `(-1)/2` равно -1, а не -0,5. Это означает, что результаты деления могут неожиданно различаться в зависимости от типа двух операндов, а из-за динамической типизации Python бывает трудно определить возможные типы операндов.416417(Споры ведутся о том, является ли это *действительно* проектным недостатком и стоит ли ломать существующий код для его исправления. Это вызвало бесконечные обсуждения в python-dev, а в июле 2001 года вылилось в шквал едко-саркастических сообщений в *comp.lang.python*. Я не буду выступать ни за одну из сторон и ограничусь описанием того, что реализовано в 2.2. Прочтите [**PEP 238**](https://python-all.ru/3.5/whatsnew/2.2.html) для сводки аргументов и контраргументов.)418419Поскольку это изменение может нарушить работу существующего кода, его внедряют очень постепенно. Переход начинается в Python 2.2, но полное переключение произойдёт только в Python 3.0.420421Сначала я позаимствую несколько терминов из [**PEP 238**](https://python-all.ru/3.5/whatsnew/2.2.html). «Истинное деление» – это деление, знакомое большинству не-программистов: 3/2 равно 1,5, 1/4 равно 0,25 и так далее. «Деление с округлением вниз» (floor division) – это то, что оператор `/` в Python сейчас делает с целочисленными операндами; результат – это округлённое вниз значение, возвращаемое истинным делением. «Классическое деление» – это текущее смешанное поведение `/`; оно возвращает результат деления с округлением вниз, когда операнды – целые числа, и результат истинного деления, когда один из операндов – число с плавающей запятой.422423Вот изменения, которые вводит Python 2.2:424425- Новый оператор `//` – это оператор деления с округлением вниз. (Да, мы знаем, что он похож на символ комментария в C++.) `//` *всегда* выполняет деление с округлением вниз независимо от типов операндов, поэтому `1 // 2` равно 0, а `1.0 // 2.0` также равно 0,0.426427 `//` всегда доступен в Python 2.2; его не нужно включать с помощью оператора `__future__`.428- Если включить `from __future__ import division` в модуль, оператор `/` будет изменён так, чтобы возвращать результат истинного деления, поэтому `1/2` станет равно 0,5. Без оператора `__future__` `/` по-прежнему означает классическое деление. Значение по умолчанию `/` не изменится до Python 3.0.429- Классы могут определять методы с именами [`__truediv__()`](https://python-all.ru/3.5/reference/datamodel.html#object.__truediv__) и [`__floordiv__()`](https://python-all.ru/3.5/reference/datamodel.html#object.__floordiv__) для перегрузки двух операторов деления. На уровне C также есть слоты в структуре [`PyNumberMethods`](https://python-all.ru/3.5/c-api/typeobj.html#c.PyNumberMethods), чтобы типы-расширения могли определять эти операторы.430- Python 2.2 поддерживает несколько аргументов командной строки для проверки, будет ли код работать с изменённой семантикой деления. Запуск python с флагом `-Q warn` будет вызывать предупреждение каждый раз, когда деление применяется к двум целым числам. Это можно использовать, чтобы найти код, на который повлияло изменение, и исправить его. По умолчанию Python 2.2 просто выполняет классическое деление без предупреждения; предупреждение будет включено по умолчанию в Python 2.3.431432> **См. также**433>434> **[**PEP 238**](https://python-all.ru/3.5/whatsnew/2.2.html) – Изменение оператора деления**435>436> Написан Моше Задкой и Гвидо ван Россумом. Реализован Гвидо ван Россумом.437438## Изменения в поддержке Unicode439440Поддержка Unicode в Python 2.2 была немного расширена. Строки Unicode обычно хранятся как UCS-2, то есть 16-битные целые числа без знака. Python 2.2 также можно скомпилировать с использованием UCS-4 (32-битные целые числа без знака) в качестве внутренней кодировки, передав `--enable-unicode=ucs4` скрипту configure. (Также можно указать `--disable-unicode`, чтобы полностью отключить поддержку Unicode.)441442При компиляции для использования UCS-4 («широкий Python») интерпретатор может напрямую работать с символами Unicode от U+000000 до U+110000, поэтому диапазон допустимых значений для функции `unichr()` соответственно расширяется. При использовании интерпретатора, скомпилированного для UCS-2 («узкий Python»), значения больше 65535 по-прежнему будут заставлять `unichr()` вызывать исключение [`ValueError`](https://python-all.ru/3.5/library/exceptions.html#ValueError). Всё это описано в [**PEP 261**](https://python-all.ru/3.5/whatsnew/2.2.html), «Поддержка «широких» символов Unicode»; обратитесь к нему за подробностями.443444Ещё одно изменение объяснить проще. С момента появления строки Unicode поддерживали метод `encode()` для преобразования строки в выбранную кодировку, например UTF-8 или Latin-1. В Python 2.2 для 8-битных строк (но не для строк Unicode) был добавлен симметричный метод `decode([*encoding*])`. `decode()` предполагает, что строка находится в указанной кодировке, и декодирует её, возвращая то, что возвращает кодек.445446С помощью этой новой функции были добавлены кодеки для задач, не связанных напрямую с Unicode. Например, добавлены кодеки для uu-кодирования, кодирования base64 из MIME и сжатия с помощью модуля [`zlib`](https://python-all.ru/3.5/library/zlib.html#module-zlib):447448```python449>>> s = """Here is a lengthy piece of redundant, overly verbose,450... and repetitive text.451... """452>>> data = s.encode('zlib')453>>> data454'x\x9c\r\xc9\xc1\r\x80 \x10\x04\xc0?Ul...'455>>> data.decode('zlib')456'Here is a lengthy piece of redundant, overly verbose,\nand repetitive text.\n'457>>> print s.encode('uu')458begin 666 <data>459M2&5R92!I<R!A(&QE;F=T:'D@<&EE8V4@;V8@<F5D=6YD86YT+"!O=F5R;'D@460>=F5R8F]S92P*86YD(')E<&5T:71I=F4@=&5X="X*461462end463>>> "sheesh".encode('rot-13')464'furrfu'465```466467Для преобразования экземпляра класса в Unicode класс может определить метод `__unicode__()`, аналогичный [`__str__()`](https://python-all.ru/3.5/reference/datamodel.html#object.__str__).468469`encode()`, `decode()` и `__unicode__()` были реализованы Марком-Андре Лембургом. Изменения для поддержки UCS-4 внутри были реализованы Фредриком Лундом и Мартином фон Лёвисом.470471> **См. также**472>473> **[**PEP 261**](https://python-all.ru/3.5/whatsnew/2.2.html) – Поддержка «широких» символов Unicode**474>475> Автор: Paul Prescod.476477## PEP 227: Вложенные области видимости478479В Python 2.1 статически вложенные области видимости были добавлены как опциональная возможность, которую нужно было включать директивой `from __future__ import nested_scopes`. В Python 2.2 вложенные области видимости больше не нужно специально включать; теперь они присутствуют всегда. Остальная часть этого раздела – копия описания вложенных областей видимости из моего документа «Что нового в Python 2.1»; если вы читали его, когда вышла версия 2.1, можете пропустить оставшуюся часть.480481Самое большое изменение, введённое в Python 2.1 и завершённое в 2.2, касается правил областей видимости Python. В Python 2.0 в любой момент времени для поиска имён переменных использовалось не более трёх пространств имён: локальное, модульное и встроенное. Это часто удивляло людей, потому что не соответствовало их интуитивным ожиданиям. Например, вложенное рекурсивное определение функции не работает:482483```python484def f():485 ...486 def g(value):487 ...488 return g(value-1) + 1489 ...490```491492Функция `g()` всегда возбуждает исключение [`NameError`](https://python-all.ru/3.5/library/exceptions.html#NameError), потому что связывание имени `g` не находится ни в локальном пространстве имён, ни в пространстве имён уровня модуля. На практике это не представляет большой проблемы (насколько часто рекурсивно определяются вложенные функции таким образом?), но это также сделало использование оператора [`lambda`](https://python-all.ru/3.5/reference/expressions.html#lambda) более громоздким, и это было проблемой на практике. В коде, использующем [`lambda`](https://python-all.ru/3.5/reference/expressions.html#lambda), часто можно встретить копирование локальных переменных путём передачи их в качестве значений аргументов по умолчанию.493494```python495def find(self, name):496 "Return list of any entries equal to 'name'"497 L = filter(lambda x, name=name: x == name,498 self.list_attribute)499 return L500```501502В результате удобочитаемость кода Python, написанного в сильно функциональном стиле, сильно страдает.503504Самое важное изменение в Python 2.2 – это добавление в язык статической области видимости для решения этой проблемы. Первый эффект: аргумент по умолчанию `name=name` теперь не нужен в приведённом выше примере. Проще говоря, если имя переменной не получает значение внутри функции (присваиванием, операторами [`def`](https://python-all.ru/3.5/reference/compound_stmts.html#def), [`class`](https://python-all.ru/3.5/reference/compound_stmts.html#class) или [`import`](https://python-all.ru/3.5/reference/simple_stmts.html#import)), ссылки на эту переменную будут искаться в локальном пространстве имён окружающей области видимости. Более подробное объяснение правил и разбор реализации можно найти в PEP.505506Это изменение может вызвать некоторые проблемы совместимости для кода, где одно и то же имя переменной используется как на уровне модуля, так и в качестве локальной переменной внутри функции, содержащей другие определения функций. Однако это кажется маловероятным, поскольку такой код и без того был бы довольно запутанным для чтения.507508Одним из побочных эффектов изменения является то, что операторы `from module import *` и `exec` стали недопустимыми в области видимости функции при определённых условиях. Справочное руководство Python всегда утверждало, что `from module import *` допустим только на верхнем уровне модуля, но интерпретатор CPython никогда раньше этого не соблюдал. В рамках реализации вложенных областей видимости компилятор, преобразующий исходный код Python в байт-код, должен генерировать разный код для доступа к переменным в охватывающей области видимости. `from module import *` и `exec` делают невозможным для компилятора определить это, поскольку они добавляют в локальное пространство имён имена, которые невозможно узнать на этапе компиляции. Поэтому, если функция содержит определения функций или выражения [`lambda`](https://python-all.ru/3.5/reference/expressions.html#lambda) со свободными переменными, компилятор укажет на это, вызвав исключение [`SyntaxError`](https://python-all.ru/3.5/library/exceptions.html#SyntaxError).509510Чтобы сделать предыдущее объяснение немного понятнее, вот пример:511512```python513x = 1514def f():515 # Следующая строка – синтаксическая ошибка516 exec 'x=2'517 def g():518 return x519```520521Строка 4, содержащая оператор `exec`, является синтаксической ошибкой, поскольку `exec` определил бы новую локальную переменную с именем `x`, значение которой должно быть доступно через `g()`.522523Это не должно быть большим ограничением, поскольку `exec` редко используется в большинстве кода Python (а когда используется, это часто признак плохого дизайна).524525> **См. также**526>527> **[**PEP 227**](https://python-all.ru/3.5/whatsnew/2.2.html) – Статически вложенные области видимости**528>529> Написан и реализован Джереми Хилтоном.530531## Новые и улучшенные модули532533- Модуль `xmlrpclib` был добавлен в стандартную библиотеку Фредриком Лундом; он предоставляет поддержку для написания XML-RPC клиентов. XML-RPC – это простой протокол удалённого вызова процедур, построенный на основе HTTP и XML. Например, следующий фрагмент получает список RSS-каналов от O’Reilly Network, а затем выводит последние заголовки для одного канала:534535 ```python536 import xmlrpclib537 s = xmlrpclib.Server(538 'http://www.oreillynet.com/meerkat/xml-rpc/server.php')539 channels = s.meerkat.getChannels()540 # channels – это список словарей, например:541 # [{'id': 4, 'title': 'Freshmeat Daily News'}542 # {'id': 190, 'title': '32Bits Online'},543 # {'id': 4549, 'title': '3DGamers'}, ... ]544545 # Получить элементы для одного канала546 items = s.meerkat.getItems( {'channel': 4} )547548 # 'items' – это ещё один список словарей, например:549 # [{'link': 'http://freshmeat.net/releases/52719/',550 # 'description': 'Утилита, которая преобразует HTML в XSL FO.',551 # {'title': 'html2fo 0.3 (По умолчанию)'}552 ```553554 Модуль `SimpleXMLRPCServer` упрощает создание простых XML-RPC серверов. Дополнительную информацию об XML-RPC можно найти на [http://www.xmlrpc.com/](https://python-all.ru/3.5/whatsnew/2.2.html).555- Новый модуль [`hmac`](https://python-all.ru/3.5/library/hmac.html#module-hmac) реализует алгоритм HMAC, описанный в [**RFC 2104**](https://python-all.ru/3.5/whatsnew/2.2.html). (Автор: Gerhard Häring.)556- Некоторые функции, которые раньше возвращали длинные кортежи, теперь возвращают псевдопоследовательности, которые по-прежнему ведут себя как кортежи, но также имеют мнемонические атрибуты, такие как memberst\_mtime или `tm_year`. Улучшенные функции включают [`stat()`](https://python-all.ru/3.5/library/stat.html#module-stat), `fstat()`, `statvfs()` и `fstatvfs()` в модуле [`os`](https://python-all.ru/3.5/library/os.html#module-os), а также `localtime()`, `gmtime()` и `strptime()` в модуле [`time`](https://python-all.ru/3.5/library/time.html#module-time).557558 Например, чтобы получить размер файла с помощью старых кортежей, пришлось бы писать что-то вроде `file_size = os.stat(filename)[stat.ST_SIZE]`, но теперь это можно написать более наглядно как `file_size = os.stat(filename).st_size`.559560 Оригинальный патч для этой функции был предоставлен Ником Мэтьюсоном.561- Профилировщик Python был значительно переработан, и исправлены различные ошибки в его выводе. (Авторы: Фред Л. Дрейк-мл. и Тим Питерс.)562- Модуль [`socket`](https://python-all.ru/3.5/library/socket.html#module-socket) может быть скомпилирован с поддержкой IPv6; укажите опцию `--enable-ipv6` в скрипте configure Python. (Автор: Jun-ichiro “itojun” Hagino.)563- В модуль [`struct`](https://python-all.ru/3.5/library/struct.html#module-struct) добавлены два новых символа форматирования для 64-битных целых чисел на платформах, поддерживающих тип C `long long`. `q` предназначен для знакового 64-битного целого числа, а `Q` – для беззнакового. Значение возвращается в длинном целочисленном типе Python. (Автор: Tim Peters.)564- В интерактивном режиме интерпретатора появилась новая встроенная функция [`help()`](https://python-all.ru/3.5/library/functions.html#help), которая использует модуль [`pydoc`](https://python-all.ru/3.5/library/pydoc.html#module-pydoc), представленный в Python 2.1, для организации интерактивной справки. `help(object)` выводит любую доступную справку об *объекте*. [`help()`](https://python-all.ru/3.5/library/functions.html#help) без аргументов запускает утилиту онлайн-справки, где можно вводить имена функций, классов или модулей для чтения их справки. (Автор: Гвидо ван Россум, с использованием модуля Ka-Ping Yee [`pydoc`](https://python-all.ru/3.5/library/pydoc.html#module-pydoc).)565- В движок SRE, лежащий в основе модуля [`re`](https://python-all.ru/3.5/library/re.html#module-re), внесены различные исправления ошибок и улучшения производительности. Например, функции [`re.sub()`](https://python-all.ru/3.5/library/re.html#re.sub) и [`re.split()`](https://python-all.ru/3.5/library/re.html#re.split) были переписаны на C. Ещё один патч ускоряет некоторые диапазоны символов Unicode в два раза, а также появился новый `finditer()` метод, возвращающий итератор по всем непересекающимся совпадениям в заданной строке. (SRE поддерживается Фредриком Лундом. Патч BIGCHARSET предоставлен Мартином фон Лёвисом.)566- Модуль [`smtplib`](https://python-all.ru/3.5/library/smtplib.html#module-smtplib) теперь поддерживает [**RFC 2487**](https://python-all.ru/3.5/whatsnew/2.2.html), «Безопасный SMTP через TLS», так что теперь можно шифровать трафик SMTP между программой на Python и агентом передачи почты, которому передаётся сообщение. [`smtplib`](https://python-all.ru/3.5/library/smtplib.html#module-smtplib) также поддерживает аутентификацию SMTP. (Автор: Gerhard Häring.)567- Модуль [`imaplib`](https://python-all.ru/3.5/library/imaplib.html#module-imaplib), поддерживаемый Пирсом Лодером, получил поддержку нескольких новых расширений: расширение NAMESPACE, определённое в [**RFC 2342**](https://python-all.ru/3.5/whatsnew/2.2.html), SORT, GETACL и SETACL. (Авторы: Энтони Бакстер и Мишель Пеллетье.)568- Разбор адресов электронной почты в модуле `rfc822` теперь соответствует [**RFC 2822**](https://python-all.ru/3.5/whatsnew/2.2.html), обновлению [**RFC 822**](https://python-all.ru/3.5/whatsnew/2.2.html). (Имя модуля *не* будет изменено на `rfc2822`.) Также добавлен новый пакет, [`email`](https://python-all.ru/3.5/library/email.html#module-email), для разбора и создания сообщений электронной почты. (Автор: Барри Варшава, работа выросла из его работы над Mailman.)569- Модуль [`difflib`](https://python-all.ru/3.5/library/difflib.html#module-difflib) теперь содержит новый класс `Differ` для создания читаемых списков изменений («дельты») между двумя последовательностями строк текста. Также появились две функции-генератора, `ndiff()` и `restore()`, которые возвращают дельту из двух последовательностей или одну из исходных последовательностей из дельты. (Черновая работа выполнена Дэвидом Гуджером, на основе кода ndiff.py Тима Питерса, который затем выполнил генераторизацию.)570- Новые константы `ascii_letters`, `ascii_lowercase` и `ascii_uppercase` были добавлены в модуль [`string`](https://python-all.ru/3.5/library/string.html#module-string). Некоторые модули в стандартной библиотеке использовали `string.letters` для обозначения диапазонов A-Za-z, но это предположение неверно при использовании локалей, потому что `string.letters` изменяется в зависимости от набора допустимых символов, определённых текущей локалью. Все ошибочные модули были исправлены для использования `ascii_letters` вместо этого. (Сообщено неизвестным лицом; исправлено Фредом Л. Дрейком-мл.)571- Модуль [`mimetypes`](https://python-all.ru/3.5/library/mimetypes.html#module-mimetypes) теперь упрощает использование альтернативных баз данных MIME-типов за счёт добавления класса `MimeTypes`, который принимает список имён файлов для разбора. (Автор: Фред Л. Дрейк-мл.)572- Класс `Timer` был добавлен в модуль [`threading`](https://python-all.ru/3.5/library/threading.html#module-threading), который позволяет планировать выполнение действия в будущем. (Автор: Итамар Штуль-Трауринг.)573574## Изменения и исправления в интерпретаторе575576Некоторые изменения затрагивают только тех, кто работает с интерпретатором Python на уровне C, – тех, кто пишет модули расширения Python, встраивает интерпретатор или просто взламывает сам интерпретатор. Если вы пишете только код на Python, то описанные здесь изменения вас почти не затронут.577578- Функции профилирования и трассировки теперь могут быть реализованы на C, что позволяет работать гораздо быстрее, чем функции на Python, и должно снизить накладные расходы профилирования и трассировки. Это будет интересно авторам сред разработки для Python. В API Python были добавлены две новые функции на C, [`PyEval_SetProfile()`](https://python-all.ru/3.5/c-api/init.html#c.PyEval_SetProfile) и [`PyEval_SetTrace()`](https://python-all.ru/3.5/c-api/init.html#c.PyEval_SetTrace). Существующие функции [`sys.setprofile()`](https://python-all.ru/3.5/library/sys.html#sys.setprofile) и [`sys.settrace()`](https://python-all.ru/3.5/library/sys.html#sys.settrace) по-прежнему существуют и просто были изменены для использования нового интерфейса на уровне C. (Автор: Фред Л. Дрейк-мл.)579- Был добавлен ещё один низкоуровневый API, представляющий интерес в первую очередь для разработчиков отладчиков Python и инструментов разработки. [`PyInterpreterState_Head()`](https://python-all.ru/3.5/c-api/init.html#c.PyInterpreterState_Head) и [`PyInterpreterState_Next()`](https://python-all.ru/3.5/c-api/init.html#c.PyInterpreterState_Next) позволяют вызывающему коду просматривать все существующие объекты интерпретатора; [`PyInterpreterState_ThreadHead()`](https://python-all.ru/3.5/c-api/init.html#c.PyInterpreterState_ThreadHead) и [`PyThreadState_Next()`](https://python-all.ru/3.5/c-api/init.html#c.PyThreadState_Next) позволяют перебирать все состояния потоков для заданного интерпретатора. (Автор: Дэвид Бизли.)580- Интерфейс сборщика мусора на уровне C был изменён, чтобы упростить написание типов расширений, поддерживающих сборку мусора, и отладку неправильного использования функций. Различные функции получили немного другую семантику, поэтому ряд функций пришлось переименовать. Расширения, использующие старый API, по-прежнему будут компилироваться, но *не* будут участвовать в сборке мусора, поэтому их обновление для версии 2.2 следует считать довольно приоритетным.581582 Чтобы обновить модуль расширения до нового API, выполните следующие шаги:583- Переименуйте `Py_TPFLAGS_GC()` в `PyTPFLAGS_HAVE_GC()`.584- **Используйте [`PyObject_GC_New()`](https://python-all.ru/3.5/c-api/gcsupport.html#c.PyObject_GC_New) или [`PyObject_GC_NewVar()`](https://python-all.ru/3.5/c-api/gcsupport.html#c.PyObject_GC_NewVar) для выделения**585586 объектов, а [`PyObject_GC_Del()`](https://python-all.ru/3.5/c-api/gcsupport.html#c.PyObject_GC_Del) для их освобождения.587- **Переименовать `PyObject_GC_Init()` в [`PyObject_GC_Track()`](https://python-all.ru/3.5/c-api/gcsupport.html#c.PyObject_GC_Track) и**588589 `PyObject_GC_Fini()` в [`PyObject_GC_UnTrack()`](https://python-all.ru/3.5/c-api/gcsupport.html#c.PyObject_GC_UnTrack).590- Удалите `PyGC_HEAD_SIZE()` из расчётов размера объекта.591- Удалите вызовы `PyObject_AS_GC()` и `PyObject_FROM_GC()`.592- Новая форматная последовательность `et` была добавлена в [`PyArg_ParseTuple()`](https://python-all.ru/3.5/c-api/arg.html#c.PyArg_ParseTuple); `et` принимает как параметр, так и имя кодировки, и преобразует параметр в заданную кодировку, если параметр оказывается строкой Unicode, или оставляет его без изменений, если это 8-битная строка, предполагая, что она уже находится в нужной кодировке. Это отличается от символа формата `es`, который предполагает, что 8-битные строки находятся в кодировке ASCII по умолчанию в Python, и преобразует их в указанную новую кодировку. (Автор: М.-А. Лембург; используется для поддержки MBCS в Windows, описанной в следующем разделе.)593- Добавлена другая функция разбора аргументов, [`PyArg_UnpackTuple()`](https://python-all.ru/3.5/c-api/arg.html#c.PyArg_UnpackTuple), которая проще и, предположительно, быстрее. Вместо указания строки формата вызывающий просто задаёт минимальное и максимальное ожидаемое количество аргументов, а также набор указателей на переменные [`PyObject*`](https://python-all.ru/3.5/c-api/structures.html#c.PyObject), которые будут заполнены значениями аргументов.594- В таблицах определений методов доступны два новых флага [`METH_NOARGS`](https://python-all.ru/3.5/c-api/structures.html#METH_NOARGS) и [`METH_O`](https://python-all.ru/3.5/c-api/structures.html#METH_O), упрощающие реализацию методов без аргументов или с одним нетипизированным аргументом. Вызов таких методов эффективнее, чем вызов соответствующего метода, использующего [`METH_VARARGS`](https://python-all.ru/3.5/c-api/structures.html#METH_VARARGS). Кроме того, старый стиль написания методов на C `METH_OLDARGS` теперь официально устарел.595- Добавлены две новые функции-обёртки [`PyOS_snprintf()`](https://python-all.ru/3.5/c-api/conversion.html#c.PyOS_snprintf) и [`PyOS_vsnprintf()`](https://python-all.ru/3.5/c-api/conversion.html#c.PyOS_vsnprintf), предоставляющие кроссплатформенные реализации для относительно новых API библиотеки C `snprintf()` и `vsnprintf()`. В отличие от стандартных функций `sprintf()` и `vsprintf()`, версии Python проверяют границы используемого буфера для защиты от переполнения буфера. (Автор: M.-A. Lemburg.)596- Функция [`_PyTuple_Resize()`](https://python-all.ru/3.5/c-api/tuple.html#c._PyTuple_Resize) лишилась неиспользуемого параметра, так что теперь она принимает 2 параметра вместо 3. Третий аргумент никогда не использовался, и при переносе кода с более ранних версий на Python 2.2 его можно просто отбросить.597598## Другие изменения и исправления599600Как обычно, было множество других улучшений и исправлений ошибок, разбросанных по всему дереву исходного кода. Поиск по журналам изменений CVS показывает, что между Python 2.1 и 2.2 было применено 527 патчей и исправлено 683 ошибки; в 2.2.1 применено 139 патчей и исправлено 143 ошибки; в 2.2.2 применено 106 патчей и исправлено 82 ошибки. Эти цифры, вероятно, занижены.601602Некоторые из наиболее заметных изменений:603604- Код порта Python для MacOS, поддерживаемый Джеком Янсеном, теперь хранится в главном дереве CVS Python, и было внесено много изменений для поддержки MacOS X.605606 Самое значительное изменение – возможность собрать Python в виде фреймворка, включаемая указанием опции `--enable-framework` скрипту configure при компиляции Python. По словам Джека Янсена, «Это устанавливает самодостаточную установку Python вместе с «клеем» фреймворка OS X в `/Library/Frameworks/Python.framework` (или другое место по выбору). Пока что от этого мало непосредственной пользы (на самом деле есть недостаток: нужно изменить PATH, чтобы найти Python), но это основа для создания полноценного приложения Python, портирования MacPython IDE, возможного использования Python в качестве стандартного скриптового языка OSA и многого другого».607608 Большинство модулей инструментария MacPython, которые взаимодействуют с API MacOS, такими как оконная система, QuickTime, скриптинг и т.д., были портированы на OS X, но оставлены закомментированными в `setup.py`. Желающие поэкспериментировать с этими модулями могут раскомментировать их вручную.609- Передача именованных аргументов встроенным функциям, которые их не принимают, теперь вызывает исключение [`TypeError`](https://python-all.ru/3.5/library/exceptions.html#TypeError) с сообщением «*функция* не принимает именованных аргументов».610- Слабые ссылки, добавленные в Python 2.1 как модуль расширения, теперь являются частью ядра, поскольку они используются в реализации классов нового стиля. Исключение [`ReferenceError`](https://python-all.ru/3.5/library/exceptions.html#ReferenceError) соответственно перемещено из модуля [`weakref`](https://python-all.ru/3.5/library/weakref.html#module-weakref) и стало встроенным исключением.611- Новый скрипт `Tools/scripts/cleanfuture.py` от Тима Питерса автоматически удаляет устаревшие операторы `__future__` из исходного кода Python.612- Во встроенную функцию [`compile()`](https://python-all.ru/3.5/library/functions.html#compile) добавлен дополнительный аргумент *flags*, так что теперь поведение операторов `__future__` можно корректно наблюдать в симулированных оболочках, например в IDLE и других средах разработки. Это описано в [**PEP 264**](https://python-all.ru/3.5/whatsnew/2.2.html). (Автор: Michael Hudson.)613- Новая лицензия, введённая в Python 1.6, не была совместима с GPL. Это исправлено небольшими текстовыми изменениями в лицензии 2.2, так что теперь снова разрешено встраивать Python в программы под GPL. Обратите внимание, что сам Python не под GPL, а распространяется по лицензии, по существу эквивалентной лицензии BSD, как и раньше. Изменения лицензии также были применены к релизам Python 2.0.1 и 2.1.1.614- При получении имени файла в Unicode на Windows Python теперь преобразует его в строку в кодировке MBCS, как используется API файлов Microsoft. Поскольку API файлов явно используют MBCS, выбор Python в пользу ASCII в качестве кодировки по умолчанию оказывается неудобным. На Unix используется набор символов локали, если доступен `locale.nl_langinfo(CODESET)`. (Поддержка Windows предоставлена Марком Хаммондом при содействии Марка-Андре Лембурга. Поддержка Unix добавлена Мартином фон Лёвисом.)615- Поддержка больших файлов теперь включена на Windows. (Автор: Tim Peters.)616- Скрипт `Tools/scripts/ftpmirror.py` теперь анализирует файл `.netrc`, если он есть. (Автор: Mike Romberg.)617- Некоторые возможности объекта, возвращаемого функцией `xrange()`, теперь устарели и вызывают предупреждения при обращении к ним; они исчезнут в Python 2.3. Объекты `xrange` пытались притворяться полноценными последовательностями, поддерживая срезы, умножение последовательностей и оператор [`in`](https://python-all.ru/3.5/reference/expressions.html#in), но эти возможности редко использовались и поэтому были ошибочными. Метод `tolist()` и атрибуты `start`, `stop`, `step` также устаревают. На уровне C четвёртый аргумент функции `PyRange_New()`, `repeat`, также устарел.618- Было множество патчей к реализации словарей, в основном для исправления потенциальных дампов ядра, если словарь содержит объекты, которые хитро изменили своё хеш-значение или изменили сам словарь, в котором содержались. Некоторое время python-dev вошёл в плавный ритм: Майкл Хадсон находил случай, приводящий к дампу ядра, Тим Питерс исправлял ошибку, Майкл находил другой случай, и так по кругу.619- На Windows Python теперь можно скомпилировать с помощью Borland C благодаря ряду патчей, предоставленных Стивеном Хансеном, хотя результат пока не полностью функционален. (Но это *есть* прогресс…)620- Ещё одно улучшение Windows: компания Wise Solutions щедро предоставила PythonLabs возможность использовать их систему InstallerMaster 8.1. Ранние инсталляторы PythonLabs для Windows использовали Wise 5.0a, который уже начинал показывать свой возраст. (Упаковано Тимом Питерсом.)621- Файлы, оканчивающиеся на `.pyw`, теперь можно импортировать в Windows. `.pyw` – это специфичное для Windows обозначение, используемое для указания, что скрипт должен запускаться с помощью PYTHONW.EXE вместо PYTHON.EXE, чтобы не появлялась консоль DOS для вывода. Этот патч позволяет импортировать такие скрипты, если они также могут использоваться как модули. (Реализовано Дэвидом Боленом.)622- На платформах, где Python использует функцию C `dlopen()` для загрузки модулей расширения, теперь можно задавать флаги, используемые `dlopen()`, с помощью функций [`sys.getdlopenflags()`](https://python-all.ru/3.5/library/sys.html#sys.getdlopenflags) и [`sys.setdlopenflags()`](https://python-all.ru/3.5/library/sys.html#sys.setdlopenflags). (Автор: Bram Stolk.)623- Встроенная функция [`pow()`](https://python-all.ru/3.5/library/functions.html#pow) больше не поддерживает 3 аргумента, когда передаются числа с плавающей запятой. `pow(x, y, z)` возвращает `(x**y) % z`, но это никогда не бывает полезным для чисел с плавающей запятой, и конечный результат непредсказуемо варьируется в зависимости от платформы. Вызов вида `pow(2.0, 8.0, 7.0)` теперь вызовет исключение [`TypeError`](https://python-all.ru/3.5/library/exceptions.html#TypeError).624625## Благодарности626627Автор хотел бы поблагодарить следующих людей за предложения, исправления и помощь с различными черновиками этой статьи: Фред Бреммер, Кейт Бриггс, Эндрю Далк, Фред Л. Дрейк-младший, Карел Феллингер, Дэвид Гуджер, Марк Хаммонд, Стивен Хансен, Майкл Хадсон, Джек Янсен, Марк-Андре Лембург, Мартин фон Лёвис, Фредрик Лунд, Майкл МакЛей, Ник Мэтьюсон, Пол Мур, Густаво Нимейер, Дон О’Доннелл, Юнас Пааласма, Тим Питерс, Йенс Кваде, Том Рейнхардт, Нил Шеменауэр, Гвидо ван Россум, Грег Уорд, Эдвард Уэлборн.628