Содержание страницы
Что нового в Python 2.1¶What’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 могут индивидуально перегружать каждую из операций <, <=, >, >=, == и !=. Новые имена магических методов:
Операция |
Имя метода |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
(Магические методы названы в честь соответствующих операторов Fortran .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, который предоставляет функции для выдачи предупреждений и фильтрации тех, которые не нужно показывать. Сторонние модули также могут использовать эту инфраструктуру для объявления устаревшими старых функций, которые они больше не хотят поддерживать.
Например, в 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. Это позволяет указать любые особые флаги командной строки или библиотеки, необходимые для конкретной платформы.
В ещё одном далеко идущем изменении механизма сборки Нил Шеменауэр перестроил всё так, что 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 также позволяет создавать объекты-прокси, которые ведут себя как слабые ссылки – объект, на который ссылаются только прокси-объекты, удаляется из памяти. Однако вместо явного вызова для получения объекта, прокси прозрачно перенаправляет все операции на исходный объект, пока тот существует. Если объект удалён, попытка использования прокси вызовет исключение 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-строки, поскольку единственным способом прикрепить какие-либо данные к функции был атрибут __doc__. Например, в веб-сервере приложений Zope функции помечаются как безопасные для публичного доступа с помощью doc-строки, а в фреймворке парсинга SPARK Джона Эйкока doc-строки содержат части грамматики BNF для разбора. Такая перегрузка неудачна, так как doc-строки на самом деле предназначены для хранения документации функции; например, это означает, что нельзя должным образом документировать функции, предназначенные для частного использования в 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: Метаданные в пакетах Python¶PEP 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, поскольку для пользователей более ранних версий Python будет выпущен новый релиз Distutils. Версия 1.0.2 Distutils включает изменения, описанные в PEP 241, а также различные исправления ошибок и улучшения. Его можно будет получить в SIG Distutils по адресу https://www.python.org/community/sigs/current/distutils-sig/.
Новые и улучшенные модули¶New and Improved Modules
Ка-Пинг Йи добавил два новых модуля:
inspect.py– для получения информации о работающем коде Python, иpydoc.py– для интерактивного преобразования строк документации в 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, разработанный Тимом Питерсом, предлагает фреймворк тестирования, основанный на выполнении встроенных примеров в документирующих строках и сравнении результатов с ожидаемым выводом. PyUnit, разработанный Стивом Пёрселлом, – это фреймворк модульного тестирования, вдохновлённый JUnit, который, в свою очередь, является адаптацией фреймворка тестирования Кента Бека на Smalltalk. Дополнительную информацию о PyUnit см. на http://pyunit.sourceforge.net/.Модуль
difflibсодержит классSequenceMatcher, который сравнивает две последовательности и вычисляет изменения, необходимые для преобразования одной последовательности в другую. Например, этот модуль можно использовать для написания инструмента, аналогичного программе Unix diff, и на самом деле пример программыTools/scripts/ndiff.pyдемонстрирует, как написать такой скрипт.curses.panel– обёртка для библиотеки panel, являющейся частью ncurses и SYSV curses, была предоставлена Томасом Геллекюмом (Thomas Gellekum). Библиотека 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, предоставлена Грантом Эдвардсом (Grant Edwards).Модуль
pstatsтеперь содержит простой интерактивный браузер статистики для отображения профилей времени выполнения программ Python, вызываемый при запуске модуля как скрипта. Предоставлено Эриком С. Рэймондом (Eric S. Raymond).Была добавлена новая зависящая от реализации функция
sys._getframe([depth]), возвращающая заданный объект фрейма из текущего стека вызовов.sys._getframe()возвращает фрейм на вершине стека вызовов; если указан необязательный целочисленный аргумент depth, функция возвращает фрейм, находящийся на depth вызовов ниже вершины стека. Например,sys._getframe(1)возвращает объект фрейма вызывающего кода.Эта функция присутствует только в CPython, но не в Jython или .NET-реализации. Используйте её для отладки и воздержитесь от использования в рабочем коде.
Другие изменения и исправления¶Other Changes and Fixes
Из-за более короткого цикла релизов в Python 2.1 было сделано относительно немного мелких изменений. Поиск по журналам изменений CVS показывает 117 применённых патчей и 136 исправленных ошибок; обе цифры, вероятно, занижены. Некоторые из наиболее заметных изменений:
Теперь опционально доступен специализированный аллокатор объектов, который должен быть быстрее системного
malloc()и иметь меньше накладных расходов памяти. Аллокатор использует функцию Cmalloc()для получения больших пулов памяти, а затем удовлетворяет мелкие запросы памяти из этих пулов. Его можно включить, указав опцию--with-pymallocскрипту configure; подробности реализации см. вObjects/obmalloc.c.Авторам C-расширений следует тестировать свой код с включённым аллокатором объектов, поскольку некорректный код может сломаться, вызывая дамп ядра во время выполнения. В C API Python есть множество функций выделения памяти, которые ранее были просто псевдонимами для библиотечных
malloc()иfree(); это означало, что если ошибочно вызвать несоответствующие функции, ошибка останется незамеченной. Когда аллокатор объектов включён, эти функции больше не являются псевдонимамиmalloc()иfree(), и вызов неправильной функции для освобождения памяти приведёт к дампу ядра. Например, если память была выделена с помощьюPyMem_New(), её нужно освобождать черезPyMem_Del(), а неfree(). Некоторые модули, входящие в состав Python, столкнулись с этой проблемой и были исправлены; несомненно, найдутся сторонние модули с той же проблемой.Аллокатор объектов был предоставлен Владимиром Марангозовым (Vladimir Marangozov).
Скорость построчного ввода-вывода файлов была улучшена, поскольку пользователи часто жалуются на его медлительность, и потому что он часто используется в качестве наивного бенчмарка. Метод
readline()файловых объектов был переписан для значительного ускорения. Точный прирост скорости зависит от платформы и от того, насколько медленной была библиотечная функцияgetc(), но составляет около 66%, а на некоторых операционных системах может быть ещё выше. Тим Питерс (Tim Peters) провёл большую часть тестов и написания кода для этого изменения, мотивированный обсуждением в comp.lang.python.Также был добавлен новый модуль и метод для файловых объектов, предоставленный Джеффом Эплером (Jeff Epler). Новый метод
xreadlines()похож на существующую встроенную функциюxrange().xreadlines()возвращает непрозрачный объект последовательности, который поддерживает только итерацию, читая по одной строке на каждой итерации, но не загружая весь файл в память, как это делает существующий методreadlines(). Используется это так:for line in sys.stdin.xreadlines(): # ... сделать что-то для каждой строки ... ...
Более подробное обсуждение изменений построчного ввода-вывода см. в сводке python-dev за 1–15 января 2001 года по адресу https://mail.python.org/pipermail/python-dev/2001-January/.
В словари был добавлен новый метод
popitem(), позволяющий деструктивно итерировать содержимое словаря; для больших словарей это может быть быстрее, поскольку не нужно создавать список всех ключей или значений.D.popitem()удаляет случайную пару(key, value)из словаряDи возвращает её в виде кортежа из двух элементов. Эта реализация была выполнена в основном Тимом Питерсом и Гвидо ван Россумом после предложения и предварительного патча от Моше Задки (Moshe Zadka).Теперь модули могут контролировать, какие имена импортируются при использовании
from module import *, путём определения атрибута__all__, содержащего список импортируемых имён. Одна из распространённых жалоб заключается в том, что если модуль импортирует другие модули, такие какsysилиstring,from module import *добавит их в пространство имён импортирующего модуля. Чтобы исправить это, просто перечислите публичные имена в__all__:# Перечислить публичные имена __all__ = ['Database', 'open']
Более строгая версия этого патча была впервые предложена и реализована Беном Вольфсоном (Ben Wolfson), но после обсуждения в python-dev была принята более мягкая окончательная версия.
Применение
repr()к строкам ранее использовало восьмеричные управляющие последовательности для непечатаемых символов; например, символ новой строки был'\012'. Это был пережиток наследия C в Python, но сегодня восьмеричная система имеет мало практического применения. Ка-Пинг Йи предложил использовать шестнадцатеричные управляющие последовательности вместо восьмеричных, а также управляющие последовательности\n,\t,\rдля соответствующих символов, и реализовал это новое форматирование.Синтаксические ошибки, обнаруженные во время компиляции, теперь могут вызывать исключения, содержащие имя файла и номер строки ошибки – приятный побочный эффект реорганизации компилятора, выполненной Джереми Хилтоном (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).