Документация Python неофициальный перевод
Содержание страницы

Что нового в Python 2.1What’s New in Python 2.1

Автор:A.M. Kuchling

ВведениеIntroduction

В этой статье описываются новые возможности Python 2.1. Хотя изменений не так много, как в Python 2.0, она всё же таит несколько приятных сюрпризов. Python 2.1 – первый релиз, управляемый через Python Enhancement Proposals (PEP), поэтому большинство значительных изменений имеют сопровождающие PEP, которые предоставляют более полную документацию и обоснование дизайна. Эта статья не пытается полностью документировать новые возможности, а просто даёт обзор для программистов на Python. Обратитесь к документации Python 2.1 или к соответствующему PEP за более подробной информацией о любой заинтересовавшей вас возможности.

Одной из недавних целей команды разработчиков Python было ускорить темп выпуска новых версий, выпуская новую версию каждые 6–9 месяцев. Python 2.1 стал первым релизом, вышедшим в таком ускоренном темпе: первая альфа-версия появилась в январе, через 3 месяца после финального выпуска Python 2.0.

Финальный выпуск Python 2.1 состоялся 17 апреля 2001 года.

PEP 227: Вложенные области видимостиPEP 227: Nested Scopes

Самое большое изменение в Python 2.1 касается правил областей видимости. В Python 2.0, в любой момент времени для поиска имён переменных использовалось не более трёх пространств имён: локальное, модуля и встроенное. Это часто удивляло людей, поскольку не соответствовало интуитивным ожиданиям. Например, вложенное рекурсивное определение функции не работает:

def f():
    ...
    def g(value):
        ...
        return g(value-1) + 1
    ...

Функция g() всегда будет вызывать исключение NameError, потому что привязка имени g не находится ни в её локальном пространстве имён, ни в пространстве имён уровня модуля. На практике это не такая уж большая проблема (как часто вы рекурсивно определяете вложенные функции таким образом?), но это также делало использование выражения lambda более громоздким, и на практике это было проблемой. В коде, использующем lambda, часто можно встретить копирование локальных переменных путём передачи их в качестве значений аргументов по умолчанию.

def find(self, name):
    "Return list of any entries equal to 'name'"
    L = filter(lambda x, name=name: x == name,
               self.list_attribute)
    return L

В результате удобочитаемость кода Python, написанного в сильно функциональном стиле, сильно страдает.

Самое значительное изменение в Python 2.1 – добавление статической области видимости для решения этой проблемы. Первый эффект: аргумент по умолчанию name=name теперь в приведённом выше примере не нужен. Проще говоря, если данной переменной не присвоено значение внутри функции (присваиванием, или операторами def, class или import), то ссылки на переменную будут искаться в локальном пространстве имён объемлющей области видимости. Более подробное объяснение правил и разбор реализации можно найти в PEP.

Это изменение может вызвать некоторые проблемы совместимости для кода, где одно и то же имя переменной используется как на уровне модуля, так и в качестве локальной переменной внутри функции, содержащей другие определения функций. Однако это кажется маловероятным, поскольку такой код и без того был бы довольно запутанным для чтения.

Один из побочных эффектов изменения: операторы from module import * и exec стали недопустимыми внутри области видимости функции при определённых условиях. Справочное руководство по Python всегда утверждало, что from module import * допустимо только на верхнем уровне модуля, но интерпретатор CPython ранее этого не проверял. В рамках реализации вложенных областей видимости компилятору, преобразующему исходный код Python в байт-код, необходимо генерировать разный код для доступа к переменным в объемлющей области. from module import * и exec не позволяют компилятору это определить, поскольку они добавляют в локальное пространство имён имена, неизвестные на этапе компиляции. Поэтому, если функция содержит определения функций или выражения lambda со свободными переменными, компилятор пометит это, возбуждая исключение SyntaxError.

Чтобы сделать предыдущее объяснение немного понятнее, вот пример:

x = 1
def f():
    # Следующая строка – синтаксическая ошибка
    exec 'x=2'
    def g():
        return x

Строка 4, содержащая оператор exec, является синтаксической ошибкой, так как exec определил бы новую локальную переменную с именем x, значение которой должно быть доступно из g().

Это не должно быть большой проблемой, поскольку exec редко используется в большинстве программ на Python (а когда используется, это часто признак плохого дизайна).

Из соображений совместимости вложенные области видимости вводились постепенно; в Python 2.1 они не включены по умолчанию, но могут быть включены в модуле с помощью future-выражения, как описано в PEP 236. (См. следующий раздел для дальнейшего обсуждения PEP 236.) В Python 2.2 вложенные области видимости станут использоваться по умолчанию, и их нельзя будет отключить, но у пользователей будет всё время жизни версии 2.1, чтобы исправить любые поломки, вызванные их введением.

См. также

PEP 227 – Статически вложенные области видимости
Написан и реализован Джереми Хилтоном.

PEP 236: Директивы __future__PEP 236: __future__ Directives

Вложенные области видимости вызвали широкую обеспокоенность опасностью поломки кода в версии 2.1, и она была настолько сильной, что разработчики Python заняли более консервативный подход. Этот подход заключается в введении соглашения: в версии N можно включать дополнительную функциональность, которая станет обязательной в версии N+1.

Синтаксис использует оператор from...import с зарезервированным именем модуля __future__. Вложенные области видимости можно включить следующим оператором:

from __future__ import nested_scopes

Хотя это выглядит как обычный оператор import, это не так; существуют строгие правила, где может размещаться такой future-оператор. Они могут быть только в начале модуля и должны предшествовать любому коду Python или обычным операторам import. Это связано с тем, что такие операторы могут влиять на то, как компилятор байт-кода Python разбирает код и генерирует байт-код, поэтому они должны предшествовать любым операторам, которые приводят к генерации байт-кода.

См. также

PEP 236 – Назад к __future__
Написан Тимом Питерсом, в основном реализован Джереми Хилтоном.

PEP 207: Богатые сравненияPEP 207: Rich Comparisons

В более ранних версиях поддержка реализации сравнений в пользовательских классах и типах расширения Python была довольно простой. Классы могли реализовать метод __cmp__(), которому передавались два экземпляра класса, и он мог вернуть только 0, если они равны, или +1/-1, если нет; метод не мог вызвать исключение или вернуть что-либо, кроме булевого значения. Пользователи Numeric Python часто находили эту модель слишком слабой и ограничивающей, потому что в программах численных расчётов, для которых используется Numeric Python, было бы полезнее выполнять поэлементное сравнение двух матриц, возвращая матрицу с результатами заданного сравнения для каждого элемента. Если две матрицы разного размера, сравнение должно иметь возможность вызвать исключение для сигнализации об ошибке.

В Python 2.1 были добавлены богатые сравнения для поддержки этой потребности. Теперь классы Python могут индивидуально перегружать каждую из операций <, <=, >, >=, == и !=. Новые имена магических методов:

Операция Имя метода
< __lt__()
<= __le__()
> __gt__()
>= __ge__()
== __eq__()
!= __ne__()

(Магические методы названы в честь соответствующих операторов Фортрана .LT., .LE. и т.д. Программисты, работающие с числами, почти наверняка хорошо знакомы с этими именами и найдут их легко запоминающимися.)

Каждый из этих магических методов имеет вид method(self, other), где self – объект слева от оператора, а other – объект справа. Например, выражение A < B вызовет A.__lt__(B).

Каждый из этих магических методов может возвращать что угодно: логическое значение, матрицу, список или любой другой объект Python. Альтернативно они могут вызвать исключение, если сравнение невозможно, противоречиво или иначе бессмысленно.

Встроенная функция cmp(A,B)() может использовать механизм расширенных сравнений, и теперь принимает необязательный аргумент, указывающий, какую операцию сравнения использовать; он задаётся одной из строк "<", "<=", ">", ">=", "==" или "!=". Если вызвана без необязательного третьего аргумента, cmp() вернёт только -1, 0 или +1, как в предыдущих версиях Python; в противном случае она вызовет соответствующий метод и может вернуть любой объект Python.

Есть также соответствующие изменения, интересные программистам на C: новый слот tp_richcmp в объектах типов и API для выполнения заданного расширенного сравнения. Я не буду описывать здесь C API, но отсылаю вас к PEP 207 или к документации по C API для Python 2.1 для полного списка связанных функций.

См. также

PEP 207 – Расширенные сравнения
Написан Гвидо ван Россумом, во многом основан на более ранней работе Дэвида Ашера и реализован Гвидо ван Россумом.

PEP 230: Инфраструктура предупрежденийPEP 230: Warning Framework

За 10 лет своего существования Python накопил некоторое количество устаревших модулей и функций. Трудно понять, когда функцию можно безопасно удалить, поскольку невозможно узнать, сколько кода её использует – возможно, ни одна программа от неё не зависит, а возможно, многие. Чтобы обеспечить более структурированное удаление старых функций, была добавлена инфраструктура предупреждений. Когда разработчики Python хотят избавиться от функции, она сначала вызывает предупреждение в следующей версии Python. Затем следующая версия Python может удалить эту функцию, и у пользователей будет полный цикл релиза, чтобы убрать использование старой функции.

Python 2.1 добавляет инфраструктуру предупреждений (warnings), используемую в этой схеме. Появляется модуль warnings, предоставляющий функции для выдачи предупреждений и фильтрации тех, которые не нужно показывать. Сторонние модули также могут использовать эту инфраструктуру для пометки устаревших возможностей, которые они больше не хотят поддерживать.

Например, в Python 2.1 модуль regex является устаревшим, поэтому его импорт вызывает предупреждение:

>>> import regex
__main__:1: DeprecationWarning: the regex module
         is deprecated; please use the re module
>>>

Предупреждения можно выдавать вызовом функции warnings.warn():

warnings.warn("feature X no longer supported")

Первый параметр – сообщение предупреждения; дополнительные необязательные параметры могут использоваться для указания конкретной категории предупреждения.

Можно добавлять фильтры для отключения определённых предупреждений; регулярное выражение может применяться к сообщению или имени модуля, чтобы подавить предупреждение. Например, у вас может быть программа, использующая модуль regex, и нет времени прямо сейчас переделывать её на использование модуля re. Предупреждение можно подавить вызовом:

import warnings
warnings.filterwarnings(action = 'ignore',
                        message='.*regex module is deprecated',
                        category=DeprecationWarning,
                        module = '__main__')

Таким образом добавляется фильтр, который применяется только к предупреждениям класса DeprecationWarning, возникающим в модуле __main__, и использует регулярное выражение для поиска сообщения об устаревании модуля regex; такие предупреждения будут игнорироваться. Предупреждения также могут выводиться только один раз, при каждом выполнении проблемного кода или превращаться в исключения, которые остановят программу (если, конечно, исключения не перехватываются обычным образом).

В C API Python также были добавлены функции для выдачи предупреждений; обратитесь к PEP 230 или документации по API Python за подробностями.

См. также

PEP 5 – Руководство по эволюции языка
Написан Полом Прескодом, чтобы определить процедуры, которым нужно следовать при удалении старых функций из Python. Политика, описанная в этом PEP, официально не принята, но итоговая политика, вероятно, не будет слишком отличаться от предложения Прескода.
PEP 230 – Инфраструктура предупреждений
Написан и реализован Гвидо ван Россумом.

PEP 229: Новая система сборкиPEP 229: New Build System

При компиляции Python пользователю приходилось вручную редактировать файл Modules/Setup, чтобы включить различные дополнительные модули; набор по умолчанию относительно невелик и ограничен модулями, компилируемыми на большинстве платформ Unix. Это означает, что на платформах Unix с гораздо большими возможностями, особенно на Linux, установки Python часто не содержат всех полезных модулей, которые могли бы быть.

Python 2.0 добавил Distutils – набор модулей для распространения и установки расширений. В Python 2.1 Distutils используются для компиляции большей части стандартной библиотеки модулей расширения, с автоматическим определением того, какие из них поддерживаются на текущей машине. Ожидается, что это сделает установку Python проще и более функциональной.

Вместо редактирования файла Modules/Setup для включения модулей во время сборки запускается скрипт setup.py из корневого каталога дистрибутива исходного кода Python, который пытается определить, какие модули можно включить, проверяя модули и заголовочные файлы в системе. Если модуль сконфигурирован в Modules/Setup, скрипт setup.py не будет пытаться скомпилировать этот модуль и доверится содержимому файла Modules/Setup. Это позволяет указать любые необычные флаги командной строки или библиотеки, необходимые для конкретной платформы.

В ещё одном далеко идущем изменении механизма сборки Нил Шеменауэр (Neil Schemenauer) перестроил структуру так, что Python теперь использует один makefile, не являющийся рекурсивным, вместо makefile в корневом каталоге и в каждом из подкаталогов Python/, Parser/, Objects/ и Modules/. Это ускоряет сборку Python, а также делает взлом Makefile более понятным и простым.

См. также

PEP 229 – Использование Distutils для сборки Python
Автор и разработчик: Э.М. Кухлинг.

PEP 205: Слабые ссылкиPEP 205: Weak References

Слабые ссылки, доступные через модуль weakref, – небольшой, но полезный новый тип данных в арсенале программиста на Python.

Хранение ссылки на объект (скажем, в словаре или списке) имеет побочный эффект: объект остаётся живым навсегда. Есть несколько конкретных случаев, когда такое поведение нежелательно; наиболее распространённый – кэши объектов, а другой – циклические ссылки в структурах данных, таких как деревья.

Например, рассмотрим мемоизирующую функцию, которая кэширует результаты другой функции f(x)(), сохраняя её аргумент и результат в словаре:

_cache = {}
def memoize(x):
    if _cache.has_key(x):
        return _cache[x]

    retval = f(x)

    # Кэшировать возвращаемый объект
    _cache[x] = retval

    return retval

Эта версия работает для простых вещей, таких как целые числа, но у неё есть побочный эффект: словарь _cache хранит ссылки на возвращаемые значения, поэтому они никогда не будут освобождены до завершения процесса Python и очистки памяти. Для целых чисел это не очень заметно, но если f() возвращает объект или структуру данных, занимающую много памяти, это может стать проблемой.

Слабые ссылки позволяют реализовать кэш, который не будет удерживать объекты в памяти дольше их времени. Если объект доступен только через слабые ссылки, он будет освобождён, и слабые ссылки укажут, что объект, на который они ссылались, больше не существует. Слабая ссылка на объект obj создаётся вызовом wr = weakref.ref(obj). Объект, на который ссылаются, возвращается при вызове слабой ссылки как функции: wr(). Она вернёт объект, на который ссылается, или None, если объект больше не существует.

Это позволяет написать функцию memoize(), кеш которой не удерживает объекты в памяти, сохраняя в нём слабые ссылки.

_cache = {}
def memoize(x):
    if _cache.has_key(x):
        obj = _cache[x]()
        # Если объект слабой ссылки всё ещё существует,
        # вернуть его
        if obj is not None: return obj

    retval = f(x)

    # Кэшировать слабую ссылку
    _cache[x] = weakref.ref(retval)

    return retval

Модуль weakref также позволяет создавать объекты-посредники (proxy), которые ведут себя как слабые ссылки – объект, на который ссылаются только такие посредники, удаляется из памяти, – но вместо явного вызова для получения объекта посредник прозрачно перенаправляет все операции на объект, пока он существует. Если объект удалён, попытка использовать посредник вызовет исключение weakref.ReferenceError.

proxy = weakref.proxy(obj)
proxy.attr   # Эквивалентно obj.attr
proxy.meth() # Эквивалентно obj.meth()
del obj
proxy.attr   # вызывает weakref.ReferenceError

См. также

PEP 205 – слабые ссылки
Автор и разработчик: Фред Л. Дрейк-младший.

PEP 232: Атрибуты функцийPEP 232: Function Attributes

В Python 2.1 к функциям можно прикреплять произвольную информацию. Раньше часто использовали строки документации для хранения информации о функциях и методах, потому что атрибут __doc__ был единственным способом связать с функцией какие-либо данные. Например, в сервере веб-приложений Zope функции помечались как безопасные для публичного доступа с помощью строки документации, а в фреймворке SPARK Джона Айкока строки документации содержат части BNF-грамматики для разбора. Такая перегрузка неудачна, поскольку строки документации на самом деле предназначены для хранения документации функции; например, это означает, что невозможно корректно документировать функции, предназначенные для частного использования в Zope.

Теперь можно устанавливать и получать произвольные атрибуты функций с помощью обычного синтаксиса Python:

def f(): pass

f.publish = 1
f.secure = 1
f.grammar = "A ::= B (C D)*"

Словарь, содержащий атрибуты, можно получить как __dict__ функции. В отличие от атрибута __dict__ экземпляров классов, у функций можно присвоить новый словарь __dict__, хотя новое значение должно быть обычным словарём Python; нельзя использовать трюки и присваивать, например, экземпляр UserDict или любой другой объект, который ведёт себя как отображение.

См. также

PEP 232 – Атрибуты функций
Автор и разработчик: Барри Уорсо.

PEP 235: Импорт модулей на платформах без учёта регистраPEP 235: Importing Modules on Case-Insensitive Platforms

В некоторых операционных системах файловые системы нечувствительны к регистру, в первую очередь это MacOS и Windows; в таких системах невозможно различить имена файлов FILE.PY и file.py, хотя они и хранят исходный регистр имени (они также сохраняют регистр).

В Python 2.1 оператор import будет работать так, чтобы имитировать чувствительность к регистру на платформах, где регистр не различается. Теперь Python по умолчанию будет искать первое точное совпадение с учётом регистра, вызывая ImportError, если такой файл не найден, поэтому import file не импортирует модуль с именем FILE.PY. Чтобы запросить поиск без учёта регистра, нужно установить переменную окружения PYTHONCASEOK перед запуском интерпретатора Python.

PEP 217: Интерактивный хук отображенияPEP 217: Interactive Display Hook

При интерактивной работе с интерпретатором Python вывод команд отображается с помощью встроенной функции repr(). В Python 2.1 переменной sys.displayhook() можно присвоить вызываемый объект, который будет вызван вместо repr(). Например, можно задать специальную функцию для красивого вывода:

>>> # Создать рекурсивную структуру данных
... L = [1,2,3]
>>> L.append(L)
>>> L # Показать стандартный вывод Python
[1, 2, 3, [...]]
>>> # Использовать pprint.pprint() в качестве функции отображения
... import sys, pprint
>>> sys.displayhook = pprint.pprint
>>> L
[1, 2, 3,  <Recursion on list with id=135143996>]
>>>

См. также

PEP 217 – Хук отображения для интерактивного использования
Автор и разработчик: Моше Задка.

PEP 208: Новая модель приведенияPEP 208: New Coercion Model

Существенно изменён способ выполнения числового приведения на уровне C. Это затронет только авторов расширений C для Python, предоставляя им большую гибкость при написании типов расширений, поддерживающих числовые операции.

Типы-расширения теперь могут устанавливать флаг типа Py_TPFLAGS_CHECKTYPES в своей структуре PyTypeObject, указывая, что они поддерживают новую модель приведения типов. В таких типах-расширениях функции числовых слотов больше не могут предполагать, что им будут переданы два аргумента одного типа; вместо этого им могут быть переданы два аргумента разных типов, и тогда они могут выполнять собственное внутреннее приведение. Если функции слота передан тип, который она не может обработать, она может указать на неудачу, вернув ссылку на синглтон Py_NotImplemented. Затем будут опробованы числовые функции другого типа; возможно, они смогут выполнить операцию; если другой тип также возвращает Py_NotImplemented, то будет возбуждено исключение TypeError. Числовые методы, написанные на Python, также могут возвращать Py_NotImplemented, заставляя интерпретатор действовать так, как будто метод не существует (возможно, будет возбуждено TypeError, возможно, будут опробованы числовые методы другого объекта).

См. также

PEP 208 – Переработка модели приведения
Автор и разработчик: Нил Шеменауэр, на основе более ранней работы Марка-Андре Лембурга. Прочтите это, чтобы понять тонкости обработки числовых операций на уровне C.

PEP 241: Метаданные в пакетах PythonPEP 241: Metadata in Python Packages

Частая жалоба пользователей Python – отсутствие единого каталога всех существующих модулей Python. Хранилища Парнаса Т. Миддлтона (http://www.vex.net/parnassus/) – крупнейший каталог модулей Python, но регистрация программного обеспечения в Хранилищах необязательна, и многие не утруждают себя этим.

В качестве первого небольшого шага к решению проблемы программное обеспечение Python, упакованное с помощью команды Distutils sdist, будет содержать файл с именем PKG-INFO, содержащий информацию о пакете, такую как его имя, версия и автор (метаданные в терминологии каталогизации). PEP 241 содержит полный список полей, которые могут присутствовать в файле PKG-INFO. Поскольку люди начали упаковывать своё программное обеспечение с помощью Python 2.1, всё больше пакетов будут включать метаданные, что позволит создавать автоматизированные системы каталогизации и экспериментировать с ними. На основе полученного опыта, возможно, удастся разработать действительно хороший каталог, а затем добавить поддержку для него в Python 2.2. Например, команды Distutils sdist и bdist_* могли бы поддерживать опцию upload, которая автоматически загружает пакет на сервер каталога.

Можно начать создавать пакеты, содержащие PKG-INFO, даже если вы не используете Python 2.1, поскольку новый выпуск Distutils будет подготовлен для пользователей более ранних версий Python. Версия 1.0.2 Distutils включает изменения, описанные в PEP 241, а также различные исправления и улучшения. Он будет доступен на Distutils SIG по адресу http://www.python.org/sigs/distutils-sig/.

См. также

PEP 241 – Метаданные для пакетов программного обеспечения Python
Автор и разработчик: Э.М. Кухлинг.
PEP 243 – Механизм загрузки в репозиторий модулей
Автор: Шон Райфшнайдер. В этом черновике PEP описывается предлагаемый механизм загрузки пакетов Python на центральный сервер.

Новые и улучшенные модулиNew and Improved Modules

  • Ка-Пинг Йи предоставил два новых модуля: inspect.py – модуль для получения информации о работающем коде Python, и pydoc.py – модуль для интерактивного преобразования docstrings в HTML или текст. В качестве бонуса, Tools/scripts/pydoc, который теперь устанавливается автоматически, использует pydoc.py для отображения документации по имени модуля, пакета или класса Python. Например, pydoc xml.dom выводит следующее:

    Python Library Documentation: package xml.dom in xml
    
    NAME
        xml.dom - W3C Document Object Model implementation for Python.
    
    FILE
        /usr/local/lib/python2.1/xml/dom/__init__.pyc
    
    DESCRIPTION
        The Python mapping of the Document Object Model is documented in the
        Python Library Reference in the section on the xml.dom package.
    
        This package contains the following modules:
          ...
    

    pydoc также включает интерактивный браузер справки на основе Tk. pydoc быстро вызывает привыкание; попробуйте!

  • В стандартную библиотеку были добавлены два модуля для модульного тестирования. Модуль doctest, предоставленный Тимом Питерсом, предоставляет фреймворк для тестирования, основанный на запуске встроенных примеров в docstrings и сравнении результатов с ожидаемым выводом. PyUnit, предоставленный Стивом Пёрселлом, – это фреймворк модульного тестирования, вдохновлённый JUnit, который, в свою очередь, является адаптацией фреймворка тестирования Smalltalk Кента Бека. См. http://pyunit.sourceforge.net/ для получения дополнительной информации о PyUnit.

  • Модуль difflib содержит класс SequenceMatcher, который сравнивает две последовательности и вычисляет изменения, необходимые для преобразования одной последовательности в другую. Например, этот модуль можно использовать для написания инструмента, похожего на программу Unix diff, и на самом деле пример программы Tools/scripts/ndiff.py демонстрирует, как написать такой скрипт.

  • curses.panel – обёртка для библиотеки panel, входящей в состав ncurses и SYSV curses, был предоставлен Томасом Геллекюмом. Библиотека panel предоставляет окна с дополнительной возможностью глубины. Окна можно перемещать выше или ниже в порядке глубины, а библиотека panel определяет, где панели перекрываются и какие части видимы.

  • Пакет PyXML прошёл через несколько релизов после Python 2.0, и Python 2.1 включает обновлённую версию пакета xml. Некоторые из примечательных изменений включают поддержку Expat 1.2 и более поздних версий, возможность для парсеров Expat обрабатывать файлы в любой кодировке, поддерживаемой Python, и различные исправления ошибок для SAX, DOM и модуля minidom.

  • Пинг также предоставил ещё один перехватчик для обработки необработанных исключений. sys.excepthook() можно установить в вызываемый объект. Когда исключение не перехвачено ни одним блоком try...except, исключение будет передано в sys.excepthook(), который может делать с ним что угодно. На Девятой конференции Python Пинг продемонстрировал применение этого перехватчика: вывод расширенной трассировки, которая включает не только стек вызовов, но также аргументы функций и локальные переменные для каждого кадра.

  • Различные функции в модуле time, такие как asctime() и localtime(), требуют аргумент с плавающей запятой, содержащий время в секундах с начала эпохи. Наиболее частое использование этих функций – работа с текущим временем, поэтому аргумент с плавающей запятой сделали необязательным; если значение не указано, будет использоваться текущее время. Например, записи в файлах журнала обычно нуждаются в строке, содержащей текущее время; в Python 2.1, time.asctime() можно использовать вместо более длинного time.asctime(time.localtime(time.time())), который требовался раньше.

    Это изменение было предложено и реализовано Томасом Воутерсом (Thomas Wouters).

  • Модуль ftplib теперь по умолчанию загружает файлы в пассивном режиме, поскольку пассивный режим с большей вероятностью работает из-за брандмауэра. Этот запрос поступил из системы отслеживания ошибок Debian, так как другие пакеты Debian используют ftplib для загрузки файлов и затем не работают из-за брандмауэра. Вряд ли это вызовет проблемы у кого-либо, потому что Netscape по умолчанию использует пассивный режим, и мало кто жалуется, но если пассивный режим не подходит для вашего приложения или сетевой конфигурации, вызовите set_pasv(0)() на объектах FTP, чтобы отключить пассивный режим.

  • В модуль socket добавлена поддержка низкоуровневого доступа к сокетам; предоставлено Грантом Эдвардсом.

  • Модуль pstats теперь содержит простой интерактивный обозреватель статистики для отображения профилей времени выполнения программ Python; запускается при выполнении модуля как скрипта. Предоставлено Эриком С. Рэймондом.

  • Новая зависящая от реализации функция sys._getframe([depth])() добавлена для возврата заданного объекта фрейма из текущего стека вызовов. sys._getframe() возвращает фрейм на вершине стека вызовов; если передан необязательный целочисленный аргумент depth, функция возвращает фрейм, находящийся на depth вызовов ниже вершины стека. Например, sys._getframe(1) возвращает объект фрейма вызывающей стороны.

    Эта функция присутствует только в CPython, но не в Jython или .NET-реализации. Используйте её для отладки и воздержитесь от использования в рабочем коде.

Другие изменения и исправленияOther Changes and Fixes

Из-за более короткого цикла релизов в Python 2.1 было сделано относительно немного мелких изменений. Поиск по журналам изменений CVS показывает 117 применённых патчей и 136 исправленных ошибок; обе цифры, вероятно, занижены. Некоторые из наиболее заметных изменений:

  • Теперь опционально доступен специализированный распределитель объектов, который должен быть быстрее системного malloc() и иметь меньшие накладные расходы памяти. Распределитель использует функцию C malloc() для получения больших пулов памяти, а затем удовлетворяет более мелкие запросы памяти из этих пулов. Его можно включить, передав опцию --with-pymalloc скрипту configure; подробности реализации см. в Objects/obmalloc.c.

    Авторам модулей-расширений на C следует тестировать свой код с включённым распределителем объектов, поскольку некорректный код может сломаться, вызывая аварийные дампы во время выполнения. В C API Python есть набор функций выделения памяти, которые ранее были просто псевдонимами для malloc() и free() из библиотеки C, то есть если вы случайно вызывали несоответствующие функции, ошибка не была заметна. Когда распределитель объектов включён, эти функции больше не являются псевдонимами malloc() и free(), и вызов неправильной функции для освобождения памяти приведёт к дампу памяти. Например, если память была выделена с помощью PyMem_New(), её необходимо освобождать с помощью PyMem_Del(), а не free(). Некоторые модули, входящие в состав Python, столкнулись с этим и были исправлены; несомненно, есть и другие сторонние модули, у которых будет та же проблема.

    Аллокатор объектов был предоставлен Владимиром Марангозовым (Vladimir Marangozov).

  • Скорость построчного файлового ввода-вывода была улучшена, поскольку люди часто жалуются на её недостаточность, и поскольку она часто используется в качестве наивного эталона. Метод readline() файловых объектов был переписан, чтобы стать намного быстрее. Точная степень ускорения будет варьироваться от платформы к платформе в зависимости от того, насколько медленной была функция getc() из библиотеки C, но составляет около 66%, и потенциально намного выше в некоторых конкретных операционных системах. Тим Питерс выполнил значительную часть тестирования и программирования для этого изменения, мотивированный обсуждением в comp.lang.python.

    Также был добавлен новый метод для файловых объектов, предоставленный Джеффом Эплером. Новый метод xreadlines() похож на существующую встроенную функцию xrange(). xreadlines() возвращает непрозрачный объект-последовательность, который поддерживает только итерацию, считывая одну строку на каждой итерации, но не загружая весь файл в память, как это делает существующий метод readlines(). Используется он так:

    for line in sys.stdin.xreadlines():
        # ... сделать что-то для каждой строки ...
        ...
    

    Более полное обсуждение изменений в построчном вводе-выводе можно найти в сводке python-dev за 1–15 января 2001 года по адресу http://www.python.org/dev/summary/2001-01-1/.

  • В словари добавлен новый метод popitem(), позволяющий итеративно просматривать содержимое словаря с разрушением; это может быть быстрее для больших словарей, поскольку не нужно создавать список, содержащий все ключи или значения. D.popitem() удаляет случайную пару (key, value) из словаря D и возвращает её в виде кортежа из двух элементов. Этот метод в основном реализован Тимом Питерсом и Гвидо ван Россумом после предложения и предварительного патча от Моше Задки.

  • Теперь модули могут управлять тем, какие имена импортируются при использовании from module import *, путём определения атрибута __all__, содержащего список имён, которые будут импортированы. Одна из частых жалоб: если модуль импортирует другие модули, такие как sys или string, то from module import * добавит их в пространство имён импортирующего модуля. Чтобы это исправить, просто перечислите публичные имена в __all__:

    # Перечислить публичные имена
    __all__ = ['Database', 'open']
    

    Более строгая версия этого патча была впервые предложена и реализована Беном Вольфсоном (Ben Wolfson), но после обсуждения в python-dev была принята более мягкая окончательная версия.

  • Applying repr() to strings previously used octal escapes for non-printable characters; for example, a newline was '\012'. This was a vestigial trace of Python’s C ancestry, but today octal is of very little practical use. Ka-Ping Yee suggested using hex escapes instead of octal ones, and using the \n, \t, \r escapes for the appropriate characters, and implemented this new formatting.

  • Синтаксические ошибки, обнаруженные во время компиляции, теперь могут вызывать исключения, содержащие имя файла и номер строки ошибки – приятный побочный эффект реорганизации компилятора, выполненной Джереми Хилтоном (Jeremy Hylton).

  • Расширения на C, которые импортируют другие модули, были изменены для использования PyImport_ImportModule(), что означает, что они будут использовать любые установленные перехватчики импорта. Это также рекомендуется для сторонних расширений, которым необходимо импортировать какой-либо другой модуль из кода C.

  • Размер базы данных символов Unicode был уменьшен ещё на 340K благодаря Фредрику Лунду (Fredrik Lundh).

  • Были добавлены новые порты: MacOS X (Стивен Маевски), Cygwin (Джейсон Тишлер), RISCOS (Дитмар Швертбергер), Unixware 7 (Билли Дж. Алли).

А также обычный список мелких исправлений ошибок, небольших утечек памяти, правок docstring и других доработок, слишком длинный, чтобы перечислять; если интересно, смотрите полные подробности в журналах CVS.

БлагодарностиAcknowledgements

Автор хотел бы поблагодарить следующих людей за предложения по различным черновикам этой статьи: Грэм Кросс (Graeme Cross), Дэвид Гуджер (David Goodger), Джей Грейвз (Jay Graves), Майкл Хадсон (Michael Hudson), Марк-Андре Лембург (Marc-André Lemburg), Фредрик Лунд (Fredrik Lundh), Нил Шеменауэр (Neil Schemenauer), Томас Воутерс (Thomas Wouters).