Что нового в Python 2.1¶
- Автор:
А. М. Кухлинг
Вступление¶
В этой статье рассказывается о новых функциях Python 2.1. Хотя в версии 2.1 не так много изменений, как в версии Python 2.0, все же есть несколько приятных сюрпризов. 2.1 - это первый релиз, в котором используются предложения по улучшению Python, или PEPS, поэтому большинство значительных изменений сопровождаются PEPS, которые предоставляют более полную документацию и обоснование дизайна изменений. В этой статье не делается попытка полностью описать новые функции, а просто дается обзор новых возможностей для программистов на Python. Обратитесь к документации по Python 2.1 или к конкретному PEP для получения более подробной информации о любой новой функции, которая вас особенно интересует.
Одной из недавних целей команды разработчиков Python было ускорить темпы выпуска новых версий, при этом новый релиз будет выходить каждые 6-9 месяцев. 2.1 - это первый релиз, который выходит такими быстрыми темпами, а первая альфа-версия появилась в январе, через 3 месяца после выхода финальной версии 2.0.
Окончательный релиз Python 2.1 состоялся 17 апреля 2001 года.
PEP 227: Вложенные области¶
Самое большое изменение в Python 2.1 касается правил определения области видимости Python. В 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():
# The next line is a syntax error
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 - Статически вложенные области
Написана и реализована Джереми Хилтоном.
ОПТОСОЗ 236: __будущие__ директивы¶
Реакцией на вложенные области видимости стало широко распространенное беспокойство по поводу опасностей взлома кода в версии 2.1, и этого было достаточно, чтобы заставить разработчиков Python придерживаться более консервативного подхода. Этот подход заключается во введении соглашения о включении необязательной функциональности в версии N, которая станет обязательной в версии N+1.
В синтаксисе используется оператор from...import
, использующий зарезервированное имя модуля __future__
. Вложенные области могут быть активированы с помощью следующего оператора:
from __future__ import nested_scopes
Хотя это выглядит как обычный оператор import
, это не так; существуют строгие правила относительно того, куда можно поместить такой оператор future. Они могут быть только в верхней части модуля и должны предшествовать любому коду на Python или обычным операторам import
. Это связано с тем, что такие инструкции могут повлиять на то, как компилятор байт-кода Python анализирует код и генерирует байт-код, поэтому они должны предшествовать любой инструкции, которая приведет к созданию байт-кода.
См.также
- PEP 236 - Вернуться к
__future__
Написана Тимом Питерсом и в основном реализована Джереми Хилтоном.
ОПТОСОЗ 207: Подробные сравнения¶
В более ранних версиях поддержка Python для реализации сравнений пользовательских классов и типов расширений была довольно простой. Классы могли реализовывать метод __cmp__()
, которому были предоставлены два экземпляра класса, и который мог возвращать только 0, если они были равны, или +1 или -1, если они не были равны; метод не мог вызывать исключение или возвращать что-либо, кроме логического значения. Пользователи Numeric Python часто находили эту модель слишком слабой и ограничивающей, поскольку в программах для обработки чисел, для которых используется numeric Python, было бы более полезно иметь возможность выполнять поэлементные сравнения двух матриц, возвращая матрицу, содержащую результаты данного сравнения для каждого элемента. Если две матрицы имеют разные размеры, то при сравнении должно быть создано исключение, сигнализирующее об ошибке.
В Python 2.1 были добавлены расширенные сравнения, чтобы удовлетворить эту потребность. Классы Python теперь могут по отдельности перегружать каждую из операций <
, <=
, >
, >=
, ==
, и !=
. Новые названия магических методов таковы:
Операция |
Название метода |
---|---|
|
|
|
|
|
|
|
|
|
|
|
(Магические методы названы в честь соответствующих операторов Fortran .LT.
. .LE.
, & c. Программисты-программисты-программисты с числовым программированием почти наверняка хорошо знакомы с этими названиями и легко их запомнят.)
Каждый из этих магических методов имеет вид method(self, other)
, где self
будет объектом в левой части оператора, в то время как other
будет объектом в правой части. Например, выражение A < B
приведет к вызову A.__lt__(B)
.
Каждый из этих волшебных методов может возвращать все, что угодно: логическое значение, матрицу, список или любой другой объект Python. В качестве альтернативы они могут вызывать исключение, если сравнение невозможно, противоречиво или иным образом бессмысленно.
Встроенная функция cmp(A,B)
может использовать расширенный механизм сравнения и теперь принимает необязательный аргумент, указывающий, какую операцию сравнения следует использовать; он задается в виде одной из строк "<"
, "<="
, ">"
, ">="
, "=="
, или "!="
. Если вызывается без необязательного третьего аргумента, cmp()
вернет только -1, 0 или +1, как в предыдущих версиях Python; в противном случае он вызовет соответствующий метод и может вернуть любой объект Python.
Также есть соответствующие изменения, представляющие интерес для программистов на C; в type objects появился новый слот tp_richcmp
и API для выполнения данного расширенного сравнения. Я не буду здесь описывать C API, но отсылаю вас к PEP 207 или к документации по C API версии 2.1 для получения полного списка связанных функций.
См.также
- PEP 207 - Множество сравнений
Написана Гвидо ван Россумом, в значительной степени основана на более ранних работах Дэвида Эшера и реализована Гвидо ван Россумом.
ОПТОСОЗ 230: Система предупреждения¶
За 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 - Рекомендации по развитию языка
Написана Полом Прескодом (Paul Prescod), чтобы указать процедуры, которым следует следовать при удалении старых функций из Python. Политика, описанная в этом PEP, официально не утверждена, но, вероятно, в конечном итоге она не будет сильно отличаться от предложения Prescod.
- PEP 230 - Система предупреждений
Написана и реализована Гвидо ван Россумом.
PEP 229: Новая система сборки¶
При компиляции 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 теперь использует один make-файл, который не является рекурсивным, вместо make-файлов в верхнем каталоге и в каждом из Python/
, Parser/
, Objects/
, и Modules/
подкаталоги. Это ускоряет создание Python, а также делает взлом Makefiles более понятным и простым.
См.также
- PEP 229 - Использование Distutils для сборки Python
Написана и реализована А. М. Кухлингом.
ОПТОСОЗ 205: Слабые ссылки¶
Слабые ссылки, доступные через модуль weakref
, являются незначительным, но полезным новым типом данных в инструментарии программиста на Python.
Сохранение ссылки на объект (скажем, в словаре или списке) приводит к тому, что этот объект остается живым вечно. Есть несколько конкретных случаев, когда такое поведение нежелательно, наиболее распространенным из которых является кэширование объектов, а другим - циклические ссылки в структурах данных, таких как деревья.
Например, рассмотрим функцию запоминания, которая кэширует результаты другой функции f(x)
, сохраняя аргумент функции и его результат в словаре:
_cache = {}
def memoize(x):
if _cache.has_key(x):
return _cache[x]
retval = f(x)
# Cache the returned object
_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 weak reference object still exists,
# return it
if obj is not None: return obj
retval = f(x)
# Cache a weak reference
_cache[x] = weakref.ref(retval)
return retval
Модуль weakref
также позволяет создавать прокси-объекты, которые ведут себя как слабые ссылки - объект, на который ссылаются только прокси-объекты, освобождается, но вместо того, чтобы требовать явного вызова для извлечения объекта, прокси-сервер прозрачно перенаправляет все операции с объектом, пока объект все еще существует. Если объект освобожден, попытка использовать прокси-сервер приведет к возникновению исключения weakref.ReferenceError
.
proxy = weakref.proxy(obj)
proxy.attr # Equivalent to obj.attr
proxy.meth() # Equivalent to obj.meth()
del obj
proxy.attr # raises weakref.ReferenceError
См.также
- PEP 205 - Слабые ссылки
Написана и реализована Фредом Л. Дрейком-младшим.
PEP 232: Функциональные атрибуты¶
В Python 2.1 к функциям теперь может быть привязана произвольная информация. Люди часто использовали строки документации для хранения информации о функциях и методах, потому что атрибут __doc__
был единственным способом привязать какую-либо информацию к функции. Например, на сервере веб-приложений Zope функции помечены как безопасные для публичного доступа благодаря наличию строки документации, а в SPARK parsing framework Джона Эйкока строки документации содержат части грамматики BNF, которые необходимо проанализировать. Такая перегрузка вызывает сожаление, поскольку строки документации на самом деле предназначены для хранения документации по функции; например, это означает, что вы не можете должным образом документировать функции, предназначенные для частного использования в Zope.
Произвольные атрибуты теперь можно устанавливать и извлекать из функций, используя обычный синтаксис Python:
def f(): pass
f.publish = 1
f.secure = 1
f.grammar = "A ::= B (C D)*"
К словарю, содержащему атрибуты, можно получить доступ как к __dict__
функции. В отличие от атрибута __dict__
экземпляров class, в функциях вы действительно можете присвоить новому словарю значение __dict__
, хотя новое значение ограничено обычным словарем Python; вы не можете быть хитрым и присвоить ему значение UserDict
экземпляр или любой другой случайный объект, который ведет себя как отображение.
См.также
- PEP 232 - Функциональные атрибуты
Написана и реализована Барри Уоршоу.
PEP 235: Импорт модулей на платформах без учета регистра¶
В некоторых операционных системах файловые системы не чувствительны к регистру, основными примерами являются macOS и Windows; в этих системах невозможно отличить имена файлов FILE.PY
и file.py
, хотя они сохраняют имя файла в исходном регистре (они также сохраняют регистр).
В Python 2.1 оператор import
будет работать для имитации чувствительности к регистру на платформах без учета регистра. Теперь Python по умолчанию будет искать первое совпадение с учетом регистра, выдавая ImportError
, если такой файл не найден, поэтому import file
не будет импортировать модуль с именем FILE.PY
. Соответствие без учета регистра можно запросить, установив переменную окружения PYTHONCASEOK
перед запуском интерпретатора Python.
PEP 217: Крючок для интерактивного отображения¶
При интерактивном использовании интерпретатора Python вывод команд отображается с помощью встроенной функции repr()
. В Python 2.1 переменной sys.displayhook()
можно присвоить значение вызываемого объекта, который будет вызываться вместо repr()
. Например, вы можете присвоить ей значение специальной функции красивой печати:
>>> # Create a recursive data structure
... L = [1,2,3]
>>> L.append(L)
>>> L # Show Python's default output
[1, 2, 3, [...]]
>>> # Use pprint.pprint() as the display function
... import sys, pprint
>>> sys.displayhook = pprint.pprint
>>> L
[1, 2, 3, <Recursion on list with id=135143996>]
>>>
См.также
- PEP 217 - Кнопка отображения для интерактивного использования
Написана и реализована Моше Цадкой.
ОПТОСОЗ 208: Новая модель принуждения¶
Способ выполнения числового преобразования на уровне C был существенно изменен. Это затронет только авторов расширений C для Python, что позволит им более гибко писать типы расширений, поддерживающие числовые операции.
Типы расширений теперь могут устанавливать флаг типа Py_TPFLAGS_CHECKTYPES
в своей структуре PyTypeObject
, чтобы указать, что они поддерживают новую модель принуждения. В таких типах расширений функции числового интервала больше не могут предполагать, что им будут переданы два аргумента одного типа; вместо этого им могут быть переданы два аргумента разных типов, а затем они могут выполнять свое собственное внутреннее приведение. Если функции slot передается тип, который она не может обработать, она может указать на ошибку, вернув ссылку на одноэлементное значение Py_NotImplemented
. Затем будут опробованы числовые функции другого типа, и, возможно, они смогут справиться с операцией; если другой тип также возвращает Py_NotImplemented
, то будет выведено значение TypeError
. Числовые методы, написанные на Python, также могут возвращать Py_NotImplemented
, заставляя интерпретатор действовать так, как будто метод не существует (возможно, вызывая TypeError
, возможно, используя числовые методы другого объекта).
См.также
- PEP 208 - Переработка модели принуждения
Написана и реализована Нилом Шеменауэром, в значительной степени основана на более ранних работах Марка-Андре Лембурга. Прочитайте это, чтобы понять тонкости того, как теперь будут обрабатываться числовые операции на уровне Си.
PEP 241: Метаданные в пакетах Python¶
Распространенная жалоба пользователей Python заключается в том, что не существует единого каталога всех существующих модулей Python. T. Middleton’s Vaults of Parnassus в www.vex.net/parnassus/
(вышел на пенсию в феврале 2009, available in the Internet Archive Wayback Machine) был крупнейшим каталогом модулей Python, но регистрация программного обеспечения в Vaults необязательна, и многие люди не утруждали себя этим.
В качестве первого небольшого шага к устранению проблемы программное обеспечение 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. Версия 1.0.2 дистрибутива включает изменения, описанные в PEP 241, а также различные исправления ошибок и улучшения. Она будет доступна в каталоге дистрибутива по адресу https://www.python.org/community/sigs/current/distutils-sig/.
Новые и улучшенные модули¶
Ка-Пинг Йи представил два новых модуля:
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
также включает браузер интерактивной справки на основе технических условий.pydoc
быстро вызывает привыкание; попробуйте!В стандартную библиотеку были добавлены два разных модуля для модульного тестирования. Модуль
doctest
, созданный Тимом Питерсом, предоставляет платформу тестирования, основанную на запуске встроенных примеров в docstrings и сравнении результатов с ожидаемым результатом. PyUnit, разработанный Стивом Перселлом, представляет собой платформу модульного тестирования, вдохновленную JUnit, которая, в свою очередь, была адаптацией платформы Smalltalk от Кента Бека. Смотрите https://pyunit.sourceforge.net/ для получения дополнительной информации о PyUnit.Модуль
difflib
содержит классSequenceMatcher
, который сравнивает две последовательности и вычисляет изменения, необходимые для преобразования одной последовательности в другую. Например, этот модуль можно использовать для написания инструмента, аналогичного программе Unix diff, и на самом деле пример программыTools/scripts/ndiff.py
демонстрирует, как написать такой скрипт.:mod:`curses.panel`Томас Геллекум (Thomas Gellekum) разработал оболочку для библиотеки панелей, которая является частью ncurses и SYSV curses. Библиотека панелей предоставляет Windows дополнительную функцию глубины. Окна можно перемещать выше или ниже по глубине, а библиотека панелей определяет, где панели перекрываются и какие разделы видны.
Начиная с версии Python 2.0, пакет PyXML претерпел несколько изменений, а версия Python 2.1 включает обновленную версию пакета
xml
. Некоторые из примечательных изменений включают поддержку Expat 1.2 и более поздних версий, возможность синтаксических анализаторов Expat обрабатывать файлы в любой кодировке, поддерживаемой Python, а также различные исправления для SAX, DOM и модуляminidom
.Ping также добавил еще один механизм для обработки неперехваченных исключений.
sys.excepthook()
может быть присвоено вызываемому объекту. Когда исключение не перехватывается никакими блокамиtry
…except
, исключение передается вsys.excepthook()
, который затем может делать все, что ему заблагорассудится. На Девятой конференции по Python компания Ping продемонстрировала приложение для этого хука: печать расширенной трассировки, в которой не только перечисляются фреймы стека, но также перечисляются аргументы функции и локальные переменные для каждого фрейма.Для различных функций в модуле
time
, таких какasctime()
иlocaltime()
, требуется аргумент с плавающей запятой, содержащий время в секундах с момента начала эпохи. Чаще всего эти функции используются для работы с текущим временем, поэтому аргумент с плавающей запятой стал необязательным; если значение не указано, будет использоваться текущее время. Например, для записей в файле журнала обычно требуется строка, содержащая текущее время; в Python 2.1 можно использоватьtime.asctime()
вместо более длинногоtime.asctime(time.localtime(time.time()))
, который требовался ранее.Это изменение было предложено и реализовано Томасом Ваутерсом.
Модуль
ftplib
теперь по умолчанию извлекает файлы в пассивном режиме, поскольку пассивный режим с большей вероятностью будет работать из-за брандмауэра. Этот запрос поступил из системы отслеживания ошибок Debian, поскольку другие пакеты Debian используютftplib
для извлечения файлов, а затем не работают из-за брандмауэра. Маловероятно, что это вызовет у кого-либо проблемы, поскольку Netscape по умолчанию использует пассивный режим, и мало кто жалуется, но если пассивный режим не подходит для вашего приложения или настройки сети, вызовитеset_pasv(0)
на FTP-объектах, чтобы отключить пассивный режим.Поддержка необработанного доступа к сокету была добавлена в модуль
socket
, созданный Грантом Эдвардсом.Модуль
pstats
теперь содержит простой интерактивный браузер статистики для отображения временных профилей программ на Python, который запускается при запуске модуля в виде скрипта. Автор: Эрик С. Рэймонд.Добавлена новая функция, зависящая от реализации,
sys._getframe([depth])
, которая возвращает данный объект frame из текущего стека вызовов.sys._getframe()
возвращает кадр, находящийся в верхней части стека вызовов; если указан необязательный целочисленный аргумент depth, то функция возвращает кадр, который находится в глубине вызовов ниже вершины стека. Например,sys._getframe(1)
возвращает объект frame вызывающего объекта.Эта функция присутствует только в CPython, но не в Jython или других реализациях .NET. Используйте ее для отладки и не поддавайтесь искушению использовать ее в рабочем коде.
Другие изменения и исправления¶
В Python 2.1 было внесено относительно немного небольших изменений из-за более короткого цикла выпуска. Поиск по журналам изменений CVS выявил 117 примененных исправлений и 136 исправленных ошибок; обе цифры, вероятно, занижены. Некоторые из наиболее заметных изменений - это:
Теперь опционально доступен специализированный распределитель объектов, который должен быть быстрее, чем system
malloc()
, и иметь меньшую нагрузку на память. Распределитель использует функцию Cmalloc()
для получения больших пулов памяти, а затем выполняет меньшие запросы к памяти из этих пулов. Это можно включить, указав опцию--with-pymalloc
в сценарии configure; подробности реализации см. в разделеObjects/obmalloc.c
.Авторам модулей расширения C следует тестировать свой код с включенным распределителем объектов, поскольку какой-либо неправильный код может сломаться, что приведет к дампам ядра во время выполнения. В C API Python есть множество функций выделения памяти, которые ранее были просто псевдонимами для библиотеки C
malloc()
иfree()
, что означает, что если вы случайно вызовете несовпадающие функции, ошибка не будет заметна. Когда распределитель объектов включен, эти функции больше не являются псевдонимамиmalloc()
иfree()
, и вызов неправильной функции для освобождения памяти приведет к получению дампа ядра. Например, если память была выделена с использованиемPyMem_New
, она должна быть освобождена с использованием:c:func:PyMem_Del, а неfree()
. Несколько модулей, входящих в состав Python, столкнулись с этой проблемой, и их пришлось исправить; несомненно, есть и другие сторонние модули, которые столкнутся с такой же проблемой.Распределитель объектов был создан Владимиром Марангозовым.
Скорость линейно-ориентированного файлового ввода-вывода была улучшена, потому что люди часто жалуются на его низкую скорость, а также потому, что он часто использовался в качестве наивного ориентира. Таким образом, метод
readline()
файловых объектов был переписан, чтобы быть намного быстрее. Точная величина ускорения будет варьироваться от платформы к платформе в зависимости от того, насколько медленной была библиотека Cgetc()
, но составляет около 66% и потенциально намного быстрее в некоторых конкретных операционных системах. Тим Питерс провел большую часть сравнительного анализа и разработки кода для этого изменения, мотивированного обсуждением в comp.lang.python.Также были добавлены новый модуль и метод для файловых объектов, разработанные Джеффом Эплером. Новый метод,
xreadlines()
, аналогичен существующему встроенномуxrange()
.xreadlines()
возвращает непрозрачный объект sequence, который поддерживает только итерацию, считывая строку на каждой итерации, но не считывая весь файл в память, как это делает существующий методreadlines()
. Вы могли бы использовать его следующим образом:for line in sys.stdin.xreadlines(): # ... do something for each line ... ...
Для более подробного обсуждения изменений в линейном вводе-выводе смотрите сводку python-dev за 1-15 января 2001 года по адресу https://mail.python.org/pipermail/python-dev/2001-January/.
В словари был добавлен новый метод,
popitem()
, позволяющий выполнять деструктивную итерацию по содержимому словаря; это может быть быстрее для больших словарей, поскольку нет необходимости создавать список, содержащий все ключи или значения.D.popitem()
удаляет случайный(key, value)
создает пару из словаряD
и возвращает ее в виде 2-кортежа. Это было реализовано в основном Тимом Питерсом и Гвидо ван Россумом после предложения и предварительного исправления Моше Цадкой.Модули теперь могут управлять тем, какие имена импортируются при использовании
from module import *
, определяя атрибут__all__
, содержащий список имен, которые будут импортированы. Одна из распространенных жалоб заключается в том, что если модуль импортирует другие модули, такие какsys
илиstring
,from module import *
, они будут добавлены в пространство имен импортирующего модуля. Чтобы исправить это, просто перечислите общедоступные имена в__all__
:# List public names __all__ = ['Database', 'open']
Более строгая версия этого исправления была впервые предложена и внедрена Беном Вулфсоном, но после некоторого обсуждения с разработчиками python была добавлена более слабая окончательная версия.
Применяя
repr()
к строкам, ранее использовались восьмеричные экранирующие символы для непечатаемых символов; например, новая строка была'\012'
. Это был рудиментарный след от предков Python на языке Си, но сегодня восьмеричный язык имеет очень мало практического применения. Ка-Пинг Йи предложил использовать шестнадцатеричные символы вместо восьмеричных и использовать\n
,\t
,\r
для соответствующих символов и реализовал это новое форматирование.Синтаксические ошибки, обнаруженные во время компиляции, теперь могут вызывать исключения, содержащие имя файла и номер строки ошибки, что является приятным побочным эффектом реорганизации компилятора, проведенной Джереми Хилтоном.
Расширения C, которые импортируют другие модули, были изменены на use
PyImport_ImportModule()
, что означает, что они будут использовать любые установленные перехватчики импорта. Это также рекомендуется для сторонних расширений, которым необходимо импортировать какой-либо другой модуль из кода C.Размер базы данных символов Unicode был уменьшен еще на 340 тысяч благодаря Фредрику Лунду.
Было добавлено несколько новых портов: macOS X (автор Стивен Маевски), Cygwin (автор Джейсон Тишлер), RISCOS (автор Дитмар Швертбергер), Unixware 7 (автор Билли Дж. Элли).
И есть обычный список мелких исправлений ошибок, незначительных утечек памяти, изменений в строках документации и других настроек, слишком длинный, чтобы его стоило перечислять; если хотите, смотрите журналы CVS для получения полной информации.
Признание¶
Автор хотел бы поблагодарить следующих людей за предложения по различным вариантам этой статьи: Грэма Кросса, Дэвида Гуджера, Джея Грейвса, Майкла Хадсона, Марка-Андре Лембурга, Фредрика Лунда, Нила Шеменауэра, Томаса Ваутерса.