Содержание страницы
Что нового в Python 2.4¶What’s New in Python 2.4
- Автор:
A.M. Kuchling
В этой статье описываются новые возможности Python 2.4.1, выпущенного 30 марта, 2005.
Python 2.4 – релиз среднего размера. Он не вносит столько изменений, как радикальный Python 2.2, но добавляет больше возможностей, чем консервативный 2.3 релиз. Наиболее значительные новые языковые возможности – это декораторы функций и выражения-генераторы; большинство остальных изменений касаются стандартной библиотеки.
Согласно журналам изменений CVS, между Python 2.3 и 2.4 было применено 481 исправление и исправлено 502 ошибки. Обе цифры, скорее всего, занижены.
Эта статья не ставит целью дать полную спецификацию каждой новой возможности, а вместо этого предоставляет краткое введение в каждую из них. За полными подробностями следует обращаться к документации Python 2.4, например, к справочнику по библиотеке Python и руководству по языку Python. Часто вас будут отсылать к PEP для конкретной новой возможности, где объясняются детали реализации и обоснование проекта.
PEP 218: Встроенные объекты множеств¶PEP 218: Built-In Set Objects
Python 2.3 представил модуль sets. Теперь в ядро Python добавлены реализации наборов данных на C в виде
двух новых встроенных типов, set(iterable) и frozenset(iterable). Они обеспечивают высокоскоростные операции для проверки членства, удаления дубликатов из последовательностей,
и для математических операций, таких как объединение, пересечение, разность и
симметрическая разность.
>>> a = set('abracadabra') # Сформировать множество из строки
>>> 'z' in a # быстрая проверка принадлежности
False
>>> a # уникальные буквы в a
set(['a', 'r', 'b', 'c', 'd'])
>>> ''.join(a) # Преобразовать обратно в строку
'arbcd'
>>> b = set('alacazam') # Сформировать второе множество
>>> a - b # буквы, которые есть в a, но нет в b
set(['r', 'd', 'b'])
>>> a | b # Буквы из a или b
set(['a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'])
>>> a & b # буквы, которые есть и в a, и в b
set(['a', 'c'])
>>> a ^ b # буквы, которые есть в a или в b, но не в обоих
set(['r', 'd', 'b', 'm', 'z', 'l'])
>>> a.add('z') # Добавить новый элемент
>>> a.update('wxy') # Добавить несколько новых элементов
>>> a
set(['a', 'c', 'b', 'd', 'r', 'w', 'y', 'x', 'z'])
>>> a.remove('x') # извлечь один элемент
>>> a
set(['a', 'c', 'b', 'd', 'r', 'w', 'y', 'z'])
Тип frozenset() – это неизменяемая версия set(). Поскольку он неизменяем и хешируем,
его можно использовать в качестве ключа словаря или элемента
другого множества.
Модуль sets остаётся в стандартной библиотеке и может быть полезен, если вы
пожелаете создать подклассы Set или ImmutableSet. В настоящее время нет
планов объявлять модуль устаревшим.
См. также
- PEP 218 – Добавление встроенного типа объектов-множеств
Изначально предложено Грегом Уилсоном, окончательно реализовано Рэймондом Хеттингером.
PEP 237: Унификация длинных целых и целых чисел¶PEP 237: Unifying Long Integers and Integers
Долгий процесс перехода по этому PEP, начатый в Python 2.2, делает ещё один шаг вперёд в Python 2.4. В 2.3 некоторые целочисленные операции, которые вели бы себя по-разному после унификации int/long, вызывали предупреждения FutureWarning
и возвращали значения, ограниченные 32 или 64 битами (в зависимости от
платформы). В 2.4 эти выражения больше не выдают предупреждение, а вместо этого возвращают другой результат, обычно длинное целое.
Проблемные выражения – это в основном сдвиги влево и длинные шестнадцатеричные
и восьмеричные константы. Например, 2 << 32 в 2.3 вызывает предупреждение,
вычисляясь в 0 на 32-битных платформах. В Python 2.4 это выражение теперь возвращает
правильный ответ: 8589934592.
См. также
- PEP 237 – Унификация длинных целых и целых чисел
Оригинальный PEP написан Моше Задкой и GvR. Изменения для 2.4 были реализованы Калле Свенссоном.
PEP 289: Выражения-генераторы¶PEP 289: Generator Expressions
Функция итераторов, введённая в Python 2.2, и модуль itertools
облегчают написание программ, которые проходят по большим наборам данных без
необходимости держать весь набор данных в памяти одновременно. Списковые включения не очень вписываются в эту картину, поскольку они создают объект списка Python, содержащий
все элементы. Это неизбежно загружает все объекты в память, что
может быть проблемой, если набор данных очень большой. При попытке написать
программу в функциональном стиле естественно написать что-то вроде:
links = [link for link in get_all_links() if not link.followed]
for link in links:
...
вместо
for link in get_all_links():
if link.followed:
continue
...
Первая форма более лаконична и, возможно, более читаема, но если вы работаете с большим количеством объектов ссылок, вам придётся писать вторую форму, чтобы избежать одновременного хранения всех объектов ссылок в памяти.
Выражения-генераторы работают аналогично списковым включениям, но не материализуют весь список; вместо этого они создают генератор, который будет возвращать элементы один за другим. Приведённый выше пример можно записать так:
links = (link for link in get_all_links() if not link.followed)
for link in links:
...
Выражения-генераторы всегда должны быть заключены в круглые скобки, как в приведённом выше примере. Скобки, обозначающие вызов функции, тоже подходят, поэтому если вы хотите создать итератор, который будет немедленно передан функции, вы можете написать:
print sum(obj.count for obj in list_all_objects())
Выражения-генераторы отличаются от списковых включений в различных мелочах. Наиболее заметно, что переменная цикла (obj в примере выше) недоступна за пределами выражения-генератора. Списковые включения оставляют переменную присвоенной её последнему значению; будущие версии Python изменят это, сделав списковые включения соответствующими выражениям-генераторам в этом отношении.
См. также
- PEP 289 – Выражения-генераторы
Предложено Рэймондом Хеттингером, реализовано Дживоном Сео при ранних усилиях, направляемых Хе-Шиком Чаном.
PEP 292: Более простые подстановки в строках¶PEP 292: Simpler String Substitutions
Некоторые новые классы в стандартной библиотеке предоставляют альтернативный механизм для подстановки переменных в строки; этот стиль подстановки может быть лучше для приложений, где неподготовленным пользователям нужно редактировать шаблоны.
Обычный способ подстановки переменных по имени – оператор %:
>>> '%(page)i: %(title)s' % {'page':2, 'title': 'The Best of Times'}
'2: The Best of Times'
При написании шаблонной строки легко забыть i или s
после закрывающей скобки. Это не большая проблема, если шаблон находится в
модуле Python, потому что вы запускаете код, получаете «Unsupported format character»
ValueError и исправляете проблему. Однако представьте приложение вроде
Mailman, где шаблонные строки или переводы редактируются пользователями, которые
не знакомы с языком Python. Синтаксис строки формата сложно
объяснить таким пользователям, и если они допустят ошибку, сложно дать
полезную обратную связь.
PEP 292 добавляет класс Template в модуль string, который использует
$ для обозначения подстановки:
>>> import string
>>> t = string.Template('$page: $title')
>>> t.substitute({'page':2, 'title': 'The Best of Times'})
'2: The Best of Times'
Если ключ отсутствует в словаре, метод substitute() вызовет
исключение KeyError. Также есть метод safe_substitute(), который
игнорирует отсутствующие ключи:
>>> t = string.Template('$page: $title')
>>> t.safe_substitute({'page':3})
'3: $title'
См. также
- PEP 292 – Упрощённые строковые подстановки
Написано и реализовано Barry Warsaw.
PEP 318: Декораторы функций и методов¶PEP 318: Decorators for Functions and Methods
Python 2.2 расширил объектную модель Python, добавив статические методы и методы класса,
но не расширил синтаксис Python, чтобы предоставить новый способ определения
статических методов или методов класса. Вместо этого нужно было написать инструкцию def
обычным способом и передать полученный метод функции staticmethod() или
classmethod(), которая оборачивала функцию как метод нового типа. Код выглядел так:
class C:
def meth (cls):
...
meth = classmethod(meth) # перепривязать имя к обёрнутому методу класса
Если метод был очень длинным, было легко пропустить или забыть
вызов classmethod() после тела функции.
Всегда предполагалось добавить синтаксис, чтобы сделать такие определения более читаемыми, но на момент выхода 2.2 хороший синтаксис не был очевиден. Сегодня хороший синтаксис всё ещё не очевиден, но пользователи просят более простого доступа к этой возможности; был добавлен новый синтаксический элемент для удовлетворения этой потребности.
Новая возможность называется «декораторы функций». Название происходит от идеи,
что classmethod(), staticmethod() и им подобные сохраняют
дополнительную информацию в объекте функции; они декорируют функции дополнительными
деталями.
Обозначение заимствовано из Java и использует символ '@' как индикатор.
С использованием нового синтаксиса приведённый выше пример был бы записан так:
class C:
@classmethod
def meth (cls):
...
@classmethod – это сокращённая запись для присваивания meth=classmethod(meth).
В более общем случае, если есть следующее:
@A
@B
@C
def f ():
...
Это эквивалентно следующему коду без декораторов:
def f(): ...
f = A(B(C(f)))
Декораторы должны находиться на строке перед определением функции, по одному декоратору на
строку, и не могут быть на той же строке, что и инструкция def, то есть @A def
f(): ... недопустимо. Можно декорировать только определения функций, либо на
уровне модуля, либо внутри класса; нельзя декорировать определения классов.
Декоратор – это просто функция, которая принимает декорируемую функцию в качестве аргумента и возвращает либо ту же функцию, либо какой-то новый объект. Возвращаемое значение декоратора не обязано быть вызываемым (хотя обычно оно вызываемое), если только к результату не будут применяться другие декораторы. Написать собственные декораторы легко. Следующий простой пример просто устанавливает атрибут у объекта функции:
>>> def deco(func):
... func.attr = 'decorated'
... return func
...
>>> @deco
... def f(): pass
...
>>> f
<function f at 0x402ef0d4>
>>> f.attr
'decorated'
>>>
В качестве чуть более реалистичного примера следующий декоратор проверяет, что переданный аргумент является целым числом:
def require_int (func):
def wrapper (arg):
assert isinstance(arg, int)
return func(arg)
return wrapper
@require_int
def p1 (arg):
print arg
@require_int
def p2(arg):
print arg*2
Пример в PEP 318 содержит более продвинутую версию этой идеи, которая позволяет как указать требуемый тип, так и проверить возвращаемый тип.
Функции-декораторы могут принимать аргументы. Если аргументы переданы, ваша
функция-декоратор вызывается только с этими аргументами и должна вернуть новую
функцию-декоратор; эта функция должна принимать одну функцию и возвращать
функцию, как описано ранее. Другими словами, @A @B @C(args) превращается в:
def f(): ...
_deco = C(args)
f = A(B(_deco(f)))
Правильно реализовать это может быть немного запутанно, но не слишком сложно.
Небольшое связанное изменение делает атрибут func_name
функций доступным для записи. Этот атрибут используется для отображения имён функций в трассировках, поэтому
декораторы должны изменять имя любой новой функции, которая создаётся и
возвращается.
См. также
- PEP 318 – Декораторы функций, методов и классов
Авторы: Kevin D. Smith, Jim Jewett и Skip Montanaro. Несколько человек написали патчи, реализующие декораторы функций, но тот, который был фактически включён, – патч #979728, написанный Mark Russell.
- https://wiki.python.org/moin/PythonDecoratorLibrary
Эта вики-страница содержит несколько примеров декораторов.
PEP 322: Обратная итерация¶PEP 322: Reverse Iteration
Новая встроенная функция reversed(seq) принимает последовательность и возвращает
итератор, который перебирает элементы последовательности в обратном порядке.
>>> for i in reversed(xrange(1,4)):
... print i
...
3
2
1
По сравнению с расширенной срезкой, например range(1,4)[::-1], reversed()
легче читается, работает быстрее и использует значительно меньше памяти.
Обратите внимание, что reversed() принимает только последовательности, а не произвольные итераторы. Если
нужно обратить итератор, сначала преобразуйте его в список с помощью list().
>>> input = open('/etc/passwd', 'r')
>>> for line in reversed(list(input)):
... print line
...
root:*:0:0:System Administrator:/var/root:/bin/tcsh
...
См. также
- PEP 322 – Обратная итерация
Написано и реализовано Raymond Hettinger.
PEP 324: Новый модуль подпроцесс¶PEP 324: New subprocess Module
Стандартная библиотека предоставляет несколько способов выполнения подпроцесса, предлагая разные возможности и разный уровень сложности. os.system(command) прост в использовании, но медленный (он запускает процесс оболочки, который выполняет команду) и опасен (нужно быть осторожным с экранированием метасимволов оболочки). Модуль popen2 предлагает классы, которые могут захватывать стандартный вывод и стандартную ошибку подпроцесса, но названия сбивают с толку. Модуль subprocess исправляет это, предоставляя единый интерфейс, который содержит все необходимые возможности.
Вместо набора классов popen2, subprocess содержит единственный класс subprocess.Popen, конструктор которого поддерживает множество различных именованных аргументов.
class Popen(args, bufsize=0, executable=None,
stdin=None, stdout=None, stderr=None,
preexec_fn=None, close_fds=False, shell=False,
cwd=None, env=None, universal_newlines=False,
startupinfo=None, creationflags=0):
args обычно представляет собой последовательность строк, которые будут аргументами программы, выполняемой как подпроцесс. (Если аргумент shell равен true, args может быть строкой, которая затем передаётся оболочке для интерпретации, как и в os.system().)
stdin, stdout и stderr определяют, какими будут потоки ввода, вывода и ошибок подпроцесса. Можно передать файловый объект или файловый дескриптор, либо использовать константу subprocess.PIPE для создания канала между подпроцессом и родительским процессом.
Конструктор имеет ряд удобных опций:
close_fds требует, чтобы все файловые дескрипторы были закрыты перед запуском подпроцесса.
cwd указывает рабочий каталог, в котором будет выполняться подпроцесс (по умолчанию используется рабочий каталог родительского процесса).
env – это словарь, задающий переменные окружения.
preexec_fn – это функция, которая вызывается перед запуском дочернего процесса.
universal_newlines открывает ввод и вывод дочернего процесса с использованием механизма универсальных символов новой строки Python.
После создания экземпляра Popen можно вызвать его метод wait() для ожидания завершения подпроцесса, poll() для проверки, завершился ли он без ожидания, или communicate(data) для отправки строки data на стандартный ввод подпроцесса. communicate(data) затем читает любые данные, отправленные подпроцессом на стандартный вывод или стандартную ошибку, и возвращает кортеж (stdout_data, stderr_data).
call() – это сокращение, которое передаёт свои аргументы конструктору Popen, ожидает завершения команды и возвращает код состояния подпроцесса. Он может служить более безопасным аналогом os.system():
sts = subprocess.call(['dpkg', '-i', '/tmp/new-package.deb'])
if sts == 0:
# Успех
...
else:
# dpkg вернул ошибку
...
Команда вызывается без использования оболочки. Если действительно нужно использовать оболочку, можно добавить shell=True в качестве именованного аргумента и передать строку вместо последовательности:
sts = subprocess.call('dpkg -i /tmp/new-package.deb', shell=True)
В PEP приведены различные примеры кода на shell и Python и показано, как их можно перевести в код Python, использующий subprocess. Настоятельно рекомендуется прочитать этот раздел PEP.
См. также
- PEP 324 - подпроцесс - новый модуль для работы с процессами
Написан и реализован Питером Острандом (Peter Åstrand) при содействии Фредрика Лунда (Fredrik Lundh) и других.
PEP 327: Decimal Data Type¶
Python всегда поддерживал числа с плавающей точкой (FP) как тип данных, основанный на базовом типе C double. Однако, хотя большинство языков программирования предоставляют тип с плавающей точкой, многие люди (даже программисты) не знают, что числа с плавающей точкой не могут точно представлять некоторые десятичные дроби. Новый тип Decimal может точно представлять эти дроби с заданной пользователем точностью.
Зачем нужен Decimal?¶Why is Decimal needed?
Ограничения возникают из-за представления, используемого для чисел с плавающей точкой. Числа с плавающей точкой состоят из трёх компонентов:
Знак, который может быть положительным или отрицательным.
Мантисса, которая представляет собой однозначное двоичное число, за которым следует дробная часть. Например,
1.01в двоичной записи – это1 + 0/2 + 1/4, или 1.25 в десятичной записи.Экспонента, которая указывает, где находится десятичная точка в представляемом числе.
Например, число 1.25 имеет положительный знак, мантиссу 1.01 (в двоичной системе) и экспоненту 0 (десятичную точку сдвигать не нужно). Число 5 имеет те же знак и мантиссу, но экспонента равна 2, потому что мантисса умножается на 4 (2 в степени экспоненты 2); 1.25 * 4 = 5.
Современные системы обычно поддерживают числа с плавающей точкой, соответствующие стандарту IEEE 754. Тип C double обычно реализуется как 64-битное число IEEE 754, в котором 52 бита отведено под мантиссу. Это означает, что числа могут быть заданы только с точностью 52 бита. Если нужно представить числа с бесконечно повторяющимся разложением, разложение обрезается после 52 бит. К сожалению, большинству программного обеспечения требуется вывод в десятичной системе, а обычные десятичные дроби часто являются бесконечными дробями в двоичной системе. Например, десятичное 1.1 в двоичной системе – это 1.0001100110011 ...; 0.1 = 1/16 + 1/32 + 1/256 плюс бесконечное число дополнительных членов. IEEE 754 вынужден обрезать эту бесконечно повторяющуюся дробь после 52 разрядов, поэтому представление оказывается слегка неточным.
Иногда эту неточность можно увидеть при выводе числа:
>>> 1.1
1.1000000000000001
Неточность не всегда видна при выводе числа, потому что преобразование из FP в строку десятичного числа выполняется библиотекой C, и большинство библиотек C стараются дать разумный результат. Однако, даже если она не отображается, неточность всё равно существует, и последующие операции могут увеличить ошибку.
Для многих приложений это не имеет значения. Если я строю график точек и отображаю их на мониторе, разница между 1.1 и 1.1000000000000001 слишком мала, чтобы быть заметной. Отчёты часто ограничивают вывод определённым количеством десятичных знаков, и если округлить число до двух, трёх или даже восьми знаков, ошибка никогда не проявляется. Однако для приложений, где это важно, реализация собственных арифметических процедур требует больших усилий.
Поэтому был создан тип Decimal.
Тип Decimal¶The Decimal type
В стандартную библиотеку Python был добавлен новый модуль decimal. Он содержит два класса: Decimal и Context. Экземпляры Decimal представляют числа, а экземпляры Context используются для инкапсуляции различных настроек, таких как точность и режим округления по умолчанию.
Экземпляры Decimal неизменяемы, как обычные целые числа и числа с плавающей точкой в Python; после создания экземпляра нельзя изменить значение, которое он представляет. Экземпляры Decimal можно создавать из целых чисел или строк:
>>> import decimal
>>> decimal.Decimal(1972)
Decimal("1972")
>>> decimal.Decimal("1.1")
Decimal("1.1")
Также можно передавать кортежи, содержащие знак, мантиссу, представленную в виде кортежа десятичных цифр, и экспоненту:
>>> decimal.Decimal((1, (1, 4, 7, 5), -2))
Decimal("-14.75")
Предостережение: бит знака – это логическое значение, поэтому 0 означает положительное число, а 1 – отрицательное.
Преобразование из чисел с плавающей запятой создаёт небольшую проблему: должно ли число с плавающей запятой, представляющее 1.1, превратиться в десятичное число для точного 1.1 или для 1.1 плюс всевозможные неточности, которые вносятся? Было решено обойти этот вопрос и не включать такое преобразование в API. Вместо этого следует преобразовать число с плавающей запятой в строку с нужной точностью и передать строку конструктору Decimal:
>>> f = 1.1
>>> decimal.Decimal(str(f))
Decimal("1.1")
>>> decimal.Decimal('%.12f' % f)
Decimal("1.100000000000")
Получив экземпляры Decimal, можно выполнять над ними обычные математические операции. Одно ограничение: возведение в степень требует целочисленного показателя:
>>> a = decimal.Decimal('35.72')
>>> b = decimal.Decimal('1.73')
>>> a+b
Decimal("37.45")
>>> a-b
Decimal("33.99")
>>> a*b
Decimal("61.7956")
>>> a/b
Decimal("20.64739884393063583815028902")
>>> a ** 2
Decimal("1275.9184")
>>> a**b
Traceback (most recent call last):
...
decimal.InvalidOperation: x ** (non-integer)
Экземпляры Decimal можно сочетать с целыми числами, но не с числами с плавающей запятой:
>>> a + 4
Decimal("39.72")
>>> a + 4.5
Traceback (most recent call last):
...
TypeError: You can interact Decimal only with int, long or Decimal data types.
>>>
Числа Decimal можно использовать с модулями math и cmath, но учтите, что они будут немедленно преобразованы в числа с плавающей запятой до выполнения операции, что может привести к потере точности и правильности. Также будет возвращено обычное число с плавающей запятой, а не Decimal.
>>> import math, cmath
>>> d = decimal.Decimal('123456789012.345')
>>> math.sqrt(d)
351364.18288201344
>>> cmath.sqrt(-d)
351364.18288201344j
Экземпляры Decimal имеют метод sqrt(), который возвращает Decimal, но если нужны другие вещи, например, тригонометрические функции, их придётся реализовать самостоятельно.
>>> d.sqrt()
Decimal("351364.1828820134592177245001")
Тип Context¶The Context type
Экземпляры класса Context инкапсулируют несколько настроек для операций с десятичными числами:
prec– это точность, количество знаков после запятой.roundingзадаёт режим округления. В модулеdecimalесть константы для различных вариантов:ROUND_DOWN,ROUND_CEILING,ROUND_HALF_EVENи другие.traps– это словарь, определяющий, что происходит при возникновении определённых ошибок: либо возбуждается исключение, либо возвращается значение. Некоторые примеры ошибочных ситуаций: деление на ноль, потеря точности и переполнение.
Существует контекст по умолчанию, локальный для потока, доступный при вызове getcontext(); можно изменить свойства этого контекста, чтобы изменить точность по умолчанию, округление или обработку исключений. Следующий пример показывает эффект изменения точности контекста по умолчанию:
>>> decimal.getcontext().prec
28
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal("0.1428571428571428571428571429")
>>> decimal.getcontext().prec = 9
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal("0.142857143")
Действие по умолчанию для ошибочных ситуаций выбирается; модуль может либо вернуть специальное значение, например, бесконечность или не-число, либо возбудить исключение:
>>> decimal.Decimal(1) / decimal.Decimal(0)
Traceback (most recent call last):
...
decimal.DivisionByZero: x / 0
>>> decimal.getcontext().traps[decimal.DivisionByZero] = False
>>> decimal.Decimal(1) / decimal.Decimal(0)
Decimal("Infinity")
>>>
Экземпляр Context также имеет различные методы форматирования чисел, такие как to_eng_string() и to_sci_string().
Для получения дополнительной информации обратитесь к документации модуля decimal, которая включает краткое руководство и справочник.
См. также
- PEP 327 – Десятичный тип данных
Автор: Facundo Batista, реализовано Facundo Batista, Eric Price, Raymond Hettinger, Aahz и Tim Peters.
- http://www.lahey.com/float.htm
В статье используется код на Fortran для иллюстрации многих проблем, которые может вызвать неточность чисел с плавающей запятой.
- https://speleotrove.com/decimal/
Описание представления на основе десятичной системы. Это представление предлагается в качестве стандарта и лежит в основе нового десятичного типа Python. Большая часть этого материала была написана Mike Cowlishaw, разработчиком языка Rexx.
PEP 328: Многострочные импорты¶PEP 328: Multi-line Imports
Одно из изменений языка – небольшое синтаксическое усовершенствование, направленное на упрощение импорта нескольких имён из модуля. В инструкции from module import names имена представляют собой последовательность имён, разделённых запятыми. Если последовательность очень длинная, можно либо написать несколько инструкций импорта из одного модуля, либо использовать обратную косую черту для переноса строк, например:
from SimpleXMLRPCServer import SimpleXMLRPCServer,\
SimpleXMLRPCRequestHandler,\
CGIXMLRPCRequestHandler,\
resolve_dotted_attribute
Синтаксическое изменение в Python 2.4 просто позволяет помещать имена в круглые скобки. Python игнорирует переводы строк внутри выражений в скобках, поэтому обратная косая черта больше не нужна:
from SimpleXMLRPCServer import (SimpleXMLRPCServer,
SimpleXMLRPCRequestHandler,
CGIXMLRPCRequestHandler,
resolve_dotted_attribute)
PEP также предлагает, чтобы все инструкции import были абсолютными импортами, с ведущим символом . для указания относительного импорта. Эта часть PEP не была реализована в Python 2.4, но была завершена в Python 2.5.
См. также
- PEP 328 – Импорты: многострочные и абсолютные/относительные
Автор: Aahz. Многострочные импорты реализованы Dima Dorfman.
PEP 331: Преобразования чисел с плавающей запятой/строк, не зависящие от локали¶PEP 331: Locale-Independent Float/String Conversions
Модуль locale позволяет программам на Python выбирать различные преобразования и соглашения отображения, локализованные для определённой страны или языка. Однако модуль старался не изменять числовую локаль, поскольку различные функции в реализации Python требовали, чтобы числовая локаль оставалась установленной на локаль 'C'. Часто это было связано с использованием C-функции atof().
Однако отказ от установки числовой локали вызывал проблемы для расширений, использующих сторонние C-библиотеки, поскольку у них не была установлена правильная локаль. Мотивирующим примером была GTK+, виджеты пользовательского интерфейса которой не отображали числа в текущей локали.
Решение, описанное в PEP, заключается в добавлении в Python API трёх новых функций, которые выполняют преобразования только в ASCII, игнорируя настройки локали:
PyOS_ascii_strtod(str, ptr)иPyOS_ascii_atof(str, ptr)обе преобразуют строку в C double.PyOS_ascii_formatd(buffer, buf_len, format, d)преобразует double в строку ASCII.
Код этих функций взят из библиотеки GLib
(https://developer-old.gnome.org/glib/2.26/), разработчики которой любезно
перелицензировали соответствующие функции и передали их Python Software
Foundation. Модуль locale теперь может изменять числовую локаль,
что позволяет расширениям, таким как GTK+, давать правильные результаты.
См. также
- PEP 331 – Преобразования чисел с плавающей запятой/строк, не зависящие от локали
Автор – Christian R. Reis, реализация – Gustavo Carneiro.
Другие изменения языка¶Other Language Changes
Ниже перечислены все изменения, которые Python 2.4 вносит в ядро языка Python.
Добавлены декораторы для функций и методов (PEP 318).
Добавлены встроенные типы
set()иfrozenset()(PEP 218). Среди других новых встроенных функций – функцияreversed(seq)(PEP 322).Добавлены генераторные выражения (PEP 289).
Некоторые числовые выражения больше не возвращают значения, ограниченные 32 или 64 битами (PEP 237).
Теперь можно заключать список имён в операторе
from module import namesв круглые скобки (PEP 328).Метод
dict.update()теперь принимает те же формы аргументов, что и конструкторdict. Сюда входят любое отображение, любой итерируемый объект с парами ключ/значение и именованные аргументы. (Предложено Raymond Hettinger.)Строковые методы
ljust(),rjust()иcenter()теперь принимают необязательный аргумент для указания символа заполнения, отличного от пробела. (Предложено Raymond Hettinger.)Строки также обзавелись методом
rsplit(), который работает как методsplit(), но разбивает строку с конца. (Предложено Sean Reifschneider.)>>> 'www.python.org'.split('.', 1) ['www', 'python.org'] 'www.python.org'.rsplit('.', 1) ['www.python', 'org']
Три именованных параметра – cmp, key и reverse – были добавлены к методу
sort()списков. Эти параметры упрощают некоторые распространённые случаи использованияsort(). Все эти параметры являются необязательными.Для параметра cmp значением должна быть функция сравнения, которая принимает два параметра и возвращает -1, 0 или +1 в зависимости от результата сравнения. Затем эта функция будет использоваться для сортировки списка. Ранее это был единственный параметр, который можно было передать в
sort().key должна быть функцией с одним параметром, которая принимает элемент списка и возвращает ключ сравнения для этого элемента. Затем список сортируется с использованием ключей сравнения. Следующий пример сортирует список без учёта регистра:
>>> L = ['A', 'b', 'c', 'D'] >>> L.sort() # сортировка с учётом регистра >>> L ['A', 'D', 'b', 'c'] >>> # использование параметра 'key' для сортировки списка >>> L.sort(key=lambda x: x.lower()) >>> L ['A', 'b', 'c', 'D'] >>> # старый способ >>> L.sort(cmp=lambda x,y: cmp(x.lower(), y.lower())) >>> L ['A', 'b', 'c', 'D']
Последний пример, использующий параметр cmp, – это старый способ выполнения сортировки без учёта регистра. Он работает, но медленнее, чем использование параметра key. Использование key вызывает метод
lower()один раз для каждого элемента списка, в то время как использование cmp вызывает его дважды для каждого сравнения, поэтому использование key экономит вызовы методаlower().Для простых ключевых функций и функций сравнения часто можно избежать выражения
lambda, используя вместо этого несвязанный метод. Например, приведённую выше сортировку без учёта регистра лучше всего записать так:>>> L.sort(key=str.lower) >>> L ['A', 'b', 'c', 'D']
Наконец, параметр reverse принимает логическое значение. Если значение истинно, список будет отсортирован в обратном порядке. Вместо
L.sort(); L.reverse()теперь можно написатьL.sort(reverse=True).Теперь гарантируется, что результаты сортировки устойчивы. Это означает, что две записи с равными ключами будут возвращены в том же порядке, в котором они поступили на вход. Например, можно отсортировать список людей по имени, а затем отсортировать список по возрасту, в результате получится список, отсортированный по возрасту, где люди с одинаковым возрастом находятся в порядке, отсортированном по имени.
(Все изменения в
sort()предложены Raymond Hettinger.)Появилась новая встроенная функция
sorted(iterable), которая работает как методlist.sort(), изменяющий объект на месте, но может использоваться в выражениях. Отличия:входными данными может быть любой итерируемый объект;
сортируется новосозданная копия, оригинал остаётся нетронутым; и
выражение возвращает новую отсортированную копию
>>> L = [9,7,8,3,2,4,1,6,5] >>> [10+i for i in sorted(L)] # можно использовать в списковом включении [11, 12, 13, 14, 15, 16, 17, 18, 19] >>> L # оригинал остаётся неизменным [9,7,8,3,2,4,1,6,5] >>> sorted('Monty Python') # любой итерируемый объект может быть входным [' ', 'M', 'P', 'h', 'n', 'n', 'o', 'o', 't', 't', 'y', 'y'] >>> # вывести содержимое словаря, отсортированное по ключам >>> colormap = dict(red=1, blue=2, green=3, black=4, yellow=5) >>> for k, v in sorted(colormap.iteritems()): ... print k, v ... black 4 blue 2 green 3 red 1 yellow 5
(Предложено Raymond Hettinger.)
Целочисленные операции больше не вызывают
OverflowWarning. ПредупреждениеOverflowWarningисчезнет в Python 2.5.Интерпретатор получил новый флаг
-m, который принимает имя, ищет соответствующий модуль вsys.pathи запускает модуль как сценарий. Например, теперь можно запустить профилировщик Python с помощьюpython -m profile. (Предложено Nick Coghlan.)Функции
eval(expr, globals, locals)иexecfile(filename, globals, locals), а также операторexecтеперь принимают любой тип отображения для параметра locals. Ранее это должен был быть обычный словарь Python. (Предложено Raymond Hettinger.)Встроенная функция
zip()иitertools.izip()теперь возвращают пустой список, если вызваны без аргументов. Ранее они вызывали исключениеTypeError. Это делает их более подходящими для использования со списками аргументов переменной длины:>>> def transpose(array): ... return zip(*array) ... >>> transpose([(1,2,3), (4,5,6)]) [(1, 4), (2, 5), (3, 6)] >>> transpose([]) []
(Предложено Raymond Hettinger.)
Сбой при импорте модуля больше не оставляет частично инициализированный объект модуля в
sys.modules. Оставленный неполный объект модуля мог ввести в заблуждение последующие импорты того же модуля, заставляя их считаться успешными, что приводило к запутанным ошибкам. (Исправлено Tim Peters.)Noneтеперь является константой; код, который присваивает новое значение имениNone, теперь вызывает синтаксическую ошибку. (Автор: Raymond Hettinger.)
Оптимизации¶Optimizations
Внутренние циклы для срезов списков и кортежей были оптимизированы и теперь работают примерно на треть быстрее. Внутренние циклы для словарей также были оптимизированы, что привело к повышению производительности для
keys(),values(),items(),iterkeys(),itervalues()иiteritems(). (Автор: Raymond Hettinger.)Механизмы увеличения и уменьшения списков были оптимизированы по скорости и эффективности использования памяти. Добавление и извлечение элементов из списков теперь выполняется быстрее благодаря более эффективным путям кода и менее частому использованию системных
realloc(). Также выигрывают списковые включения.list.extend()была также оптимизирована и больше не преобразует свой аргумент во временный список перед extending базового списка. (Автор: Raymond Hettinger.)list(),tuple(),map(),filter()иzip()теперь работают в несколько раз быстрее с аргументами, не являющимися последовательностями, которые предоставляют метод__len__(). (Автор: Raymond Hettinger.)Методы
list.__getitem__(),dict.__getitem__()иdict.__contains__()теперь реализованы как объектыmethod_descriptor, а не как объектыwrapper_descriptor. Такая форма доступа удваивает их производительность и делает их более подходящими для использования в качестве аргументов функций:map(mydict.__getitem__, keylist). (Автор: Raymond Hettinger.)Добавлен новый опкод
LIST_APPEND, который упрощает генерируемый байткод для списковых включений и ускоряет их примерно на треть. (Автор: Raymond Hettinger.)Оптимизатор байткода на маленьких окнах (peephole) был улучшен для создания более короткого и быстрого байткода; примечательно, что результирующий байткод стал более читаемым. (Улучшено Raymond Hettinger.)
Конкатенация строк в выражениях вида
s = s + "abc"иs += "abc"теперь выполняется более эффективно в определённых случаях. Эта оптимизация не будет присутствовать в других реализациях Python, таких как Jython, поэтому не следует на неё полагаться; по-прежнему рекомендуется использовать метод строкjoin(), когда нужно эффективно склеить большое количество строк. (Автор: Armin Rigo.)
Итог оптимизаций в версии 2.4: Python 2.4 выполняет тест pystone примерно на 5% быстрее, чем Python 2.3, и на 35% быстрее, чем Python 2.2. (pystone – не самый удачный тест, но это наиболее распространённое измерение производительности Python. Ваши собственные приложения могут получить от Python 2.4 больший или меньший прирост.)
Новые, улучшенные и устаревшие модули¶New, Improved, and Deprecated Modules
Как обычно, стандартная библиотека Python получила ряд улучшений и исправлений ошибок. Вот
частичный список наиболее заметных изменений, отсортированный по модулям в алфавитном порядке. Полный
список изменений можно найти в файле Misc/NEWS в дереве исходного кода или просмотрев журналы CVS.
Функция
loop()модуляasyncoreтеперь имеет параметр count, который позволяет выполнить ограниченное количество проходов по циклу опроса. По умолчанию цикл по-прежнему выполняется бесконечно.Модуль
base64теперь имеет более полную поддержку RFC 3548 для кодирования и декодирования Base64, Base32 и Base16, включая опциональное преобразование регистра и опциональные альтернативные алфавиты. (Автор: Barry Warsaw.)Модуль
bisectтеперь имеет базовую реализацию на C для улучшения производительности. (Автор: Dmitry Vasiliev.)Коллекции восточноазиатских кодеков CJKCodecs, поддерживаемые Hye-Shik Chang, были интегрированы в версию 2.4. Новые кодировки:
Китай (КНР): gb2312, gbk, gb18030, big5hkscs, hz
Китай (Тайвань): big5, cp950
- Японский: cp932, euc-jis-2004, euc-jp, euc-jisx0213, iso-2022-jp,
iso-2022-jp-1, iso-2022-jp-2, iso-2022-jp-3, iso-2022-jp-ext, iso-2022-jp-2004, shift-jis, shift-jisx0213, shift-jis-2004
Корейский: cp949, euc-kr, johab, iso-2022-kr
Были добавлены некоторые другие новые кодировки: HP Roman8, ISO_8859-11, ISO_8859-16, PCTP-154 и TIS-620.
Кодеки UTF-8 и UTF-16 теперь лучше справляются с получением частичных входных данных. Раньше класс
StreamReaderпытался прочитать больше данных, что делало невозможным возобновление декодирования из потока. Теперь методread()будет возвращать столько данных, сколько возможно, и последующие вызовы продолжат декодирование с того места, где остановились предыдущие. (Реализовано Walter Dörwald.)Появился новый модуль
collectionsдля различных специализированных типов коллекций. В настоящее время он содержит только один тип –deque, двустороннюю очередь, которая поддерживает эффективное добавление и удаление элементов с любого конца:>>> from collections import deque >>> d = deque('ghi') # создать новый deque с тремя элементами >>> d.append('j') # добавить новый элемент справа >>> d.appendleft('f') # добавить новый элемент слева >>> d # показать представление deque deque(['f', 'g', 'h', 'i', 'j']) >>> d.pop() # вернуть и удалить правый элемент 'j' >>> d.popleft() # вернуть и удалить левый элемент 'f' >>> list(d) # вывести содержимое deque ['g', 'h', 'i'] >>> 'h' in d # поиск в deque True
Некоторые модули, такие как
Queueиthreading, теперь используютcollections.dequeдля повышения производительности. (Автор: Raymond Hettinger.)Классы
ConfigParserбыли немного улучшены. Методread()теперь возвращает список файлов, которые были успешно разобраны, а методset()вызывает исключениеTypeError, если ему передан аргумент value, не являющийся строкой. (Авторы: John Belmonte и David Goodger.)Модуль
cursesтеперь поддерживает расширение ncursesuse_default_colors(). На платформах, где терминал поддерживает прозрачность, это позволяет использовать прозрачный фон. (Автор: Jörg Lehmann.)Модуль
difflibтеперь включает классHtmlDiff, который создаёт HTML-таблицу с построчным сравнением двух версий текста. (Автор: Dan Gass.)Пакет
emailбыл обновлён до версии 3.0, в которой удалены различные устаревшие API и прекращена поддержка версий Python ниже 2.3. Версия 3.0 пакета использует новый инкрементальный парсер MIME-сообщений, доступный в модулеemail.FeedParser. Новый парсер не требует чтения всего сообщения в память и не вызывает исключений, если сообщение имеет некорректный формат; вместо этого он записывает любые проблемы в атрибутdefectсообщения. (Разработан Anthony Baxter, Barry Warsaw, Thomas Wouters и другими.)Модуль
heapqбыл переписан на C. Десятикратное повышение скорости делает модуль пригодным для обработки больших объёмов данных. Кроме того, в модуле появились две новые функцииnlargest()иnsmallest(), которые используют кучи для поиска N наибольших или наименьших значений в наборе данных без затрат на полную сортировку. (Автор: Raymond Hettinger.)Модуль
httplibтеперь содержит константы для кодов состояния HTTP, определённых в различных RFC, связанных с HTTP. Константы имеют имена, такие какOK,CREATED,CONTINUEиMOVED_PERMANENTLY; для получения полного списка используйте pydoc. (Автор: Andrew Eland.)Модуль
imaplibтеперь поддерживает команду IMAP THREAD (поток) (автор: Yves Dionne) и новые методыdeleteacl()иmyrights()(автор: Arnaud Mazin).В модуле
itertoolsпоявилась функцияgroupby(iterable[, *func*]). Итерируемый объект – это то, что можно перебирать для получения потока элементов, а необязательный параметр func – функция, которая принимает элемент и возвращает значение ключа; если он опущен, ключом служит сам элемент.groupby()затем группирует элементы в подпоследовательности с совпадающими значениями ключа и возвращает серию кортежей из двух элементов, содержащих значение ключа и итератор по подпоследовательности.Вот пример для наглядности. Функция key просто возвращает, является ли число чётным или нечётным, так что результат
groupby()– это последовательные группы нечётных или чётных чисел.>>> import itertools >>> L = [2, 4, 6, 7, 8, 9, 11, 12, 14] >>> for key_val, it in itertools.groupby(L, lambda x: x % 2): ... print key_val, list(it) ... 0 [2, 4, 6] 1 [7] 0 [8] 1 [9, 11] 0 [12, 14] >>>
groupby()обычно используется с отсортированными входными данными. Логикаgroupby()похожа на фильтр Unixuniq, что удобно для удаления, подсчёта или идентификации дублирующихся элементов:>>> word = 'abracadabra' >>> letters = sorted(word) # преобразовать строку в отсортированный список букв >>> letters ['a', 'a', 'a', 'a', 'a', 'b', 'b', 'c', 'd', 'r', 'r'] >>> for k, g in itertools.groupby(letters): ... print k, list(g) ... a ['a', 'a', 'a', 'a', 'a'] b ['b', 'b'] c ['c'] d ['d'] r ['r', 'r'] >>> # вывести уникальные буквы >>> [k for k, g in groupby(letters)] ['a', 'b', 'c', 'd', 'r'] >>> # подсчитать количество вхождений букв >>> [(k, len(list(g))) for k, g in groupby(letters)] [('a', 5), ('b', 2), ('c', 1), ('d', 1), ('r', 2)]
(Добавлено Hye-Shik Chang.)
В модуле
itertoolsтакже появилась функцияtee(iterator, N), которая возвращает N независимых итераторов, копирующих iterator. Если N опущено, по умолчанию используется 2.>>> L = [1,2,3] >>> i1, i2 = itertools.tee(L) >>> i1,i2 (<itertools.tee object at 0x402c2080>, <itertools.tee object at 0x402c2090>) >>> list(i1) # исчерпать первый итератор [1, 2, 3] >>> list(i2) # исчерпать второй итератор [1, 2, 3]
Обратите внимание, что
tee()вынужден хранить копии значений, возвращаемых итератором; в худшем случае может потребоваться сохранить их все. Поэтому его следует использовать с осторожностью, если ведущий итератор может сильно опережать ведомый в длинной последовательности входных данных. Если разрыв велик, лучше использоватьlist(). Когда итераторы движутся почти синхронно,tee()идеален. Возможные применения включают итераторы для закладок, оконного просмотра или опережающего чтения. (Добавлено Raymond Hettinger.)В модуль
localeбыло добавлено несколько функций, например,bind_textdomain_codeset()для указания конкретной кодировки и семейство функцийl*gettext(), возвращающих сообщения в выбранной кодировке. (Добавлено Gustavo Niemeyer.)В функцию
basicConfig()пакетаloggingбыли добавлены некоторые именованные аргументы для упрощения настройки логирования. По умолчанию сообщения выводятся в стандартный поток ошибок, но можно указать различные именованные аргументы, чтобы вести журнал в определённый файл, изменить формат логирования или установить уровень журналирования. Например:import logging logging.basicConfig(filename='/var/log/application.log', level=0, # записать все сообщения в лог format='%(levelname):%(process):%(thread):%(message)')
Другие дополнения пакета
loggingвключают удобный методlog(level, msg), а также классTimedRotatingFileHandler, который циклически перезаписывает файлы журнала через заданный интервал времени. В модуле уже былRotatingFileHandler, который перезаписывал журналы по достижении файлом определённого размера. Оба класса наследуются от нового классаBaseRotatingHandler, который можно использовать для реализации других обработчиков ротации.(Изменения внесены Vinay Sajip.)
Модуль
marshalтеперь использует интернированные строки при распаковке структуры данных. Это может уменьшить размер некоторых строк pickle, но основной эффект – значительное уменьшение размера файлов.pyc. (Добавлено Martin von Löwis.)Класс
NNTPмодуляnntplibполучил методыdescription()иdescriptions()для получения описаний новостных групп для одной группы или для диапазона групп. (Добавлено Jürgen A. Erhard.)В модуль
operatorбыли добавлены две новые функции:attrgetter(attr)иitemgetter(index). Обе функции возвращают вызываемые объекты, которые принимают один аргумент и возвращают соответствующий атрибут или элемент; эти вызываемые объекты отлично подходят для извлечения данных при использовании сmap()илиsorted(). Например:>>> L = [('c', 2), ('d', 1), ('a', 4), ('b', 3)] >>> map(operator.itemgetter(0), L) ['c', 'd', 'a', 'b'] >>> map(operator.itemgetter(1), L) [2, 1, 4, 3] >>> sorted(L, key=operator.itemgetter(1)) # отсортировать список по второму элементу кортежа [('d', 1), ('c', 2), ('b', 3), ('a', 4)]
(Добавлено Raymond Hettinger.)
Модуль
optparseбыл обновлён различными способами. Теперь он пропускает свои сообщения черезgettext.gettext(), что позволяет интернационализировать справочные сообщения и сообщения об ошибках Optik. В справочные сообщения для параметров теперь можно включать строку'%default', которая будет заменена на значение параметра по умолчанию. (Добавлено Greg Ward.)Долгосрочный план – объявить модуль
rfc822устаревшим в одном из будущих релизов Python в пользу пакетаemail. С этой целью функцияemail.Utils.formatdateбыла изменена, чтобы её можно было использовать как замену дляrfc822.formatdate(). Возможно, вам стоит писать новый код для обработки электронной почты с учётом этого. (Изменения внесены Anthony Baxter.)В модуль
osбыла добавлена новая функцияurandom(n), возвращающая строку, содержащую n байт случайных данных. Эта функция предоставляет доступ к платформозависимым источникам случайности, таким как/dev/urandomв Linux или Windows CryptoAPI. (Добавлено Trevor Perrin.)Ещё одна новая функция:
os.path.lexists(path)возвращает true, если файл, указанный в path, существует, независимо от того, является ли он символической ссылкой. Это отличается от существующей функцииos.path.exists(path), которая возвращает false, если path является симлинком, указывающим на несуществующий целевой объект. (Добавлено Beni Cherniavsky.)В модуль
posix, лежащий в основе модуляos, добавлена новая функцияgetsid(). (Добавлено J. Raynor.)Модуль
poplibтеперь поддерживает POP через SSL. (Добавлено Hector Urtubia.)Модуль
profileтеперь может профилировать функции-расширения на C. (Добавлено Nick Bastin.)В модуле
randomпоявился новый методgetrandbits(N), который возвращает длинное целое длиной в N бит. Существующий методrandrange()теперь используетgetrandbits()где это уместно, что делает генерацию произвольно больших случайных чисел более эффективной. (Добавлено Raymond Hettinger.)Язык регулярных выражений, принимаемый модулем
re, был расширен простыми условными выражениями, записываемыми как(?(group)A|B). group – это либо числовой идентификатор группы, либо имя группы, определенное с помощью(?P<group>...)ранее в выражении. Если указанная группа совпала, шаблон регулярного выражения A будет проверяться на строке; если группа не совпала, вместо него будет использоваться шаблон B. (Добавлено Gustavo Niemeyer.)Модуль
reбольше не является рекурсивным, благодаря огромной работе Gustavo Niemeyer. В рекурсивном движке регулярных выражений некоторые шаблоны приводят к потреблению большого объёма памяти в стеке C, и можно было переполнить стек. Например, если сопоставить 30000-байтовую строку из символовaс выражением(a|b)+, расходуется один кадр стека на символ. Python 2.3 пытался проверять переполнение стека и возбуждать исключениеRuntimeError, но некоторые шаблоны могли обойти проверку, и при невезении Python мог упасть с segfault. Движок регулярных выражений Python 2.4 может сопоставлять этот шаблон без проблем.Модуль
signalтеперь выполняет более строгую проверку ошибок в параметрах функцииsignal.signal(). Например, нельзя установить обработчик на сигналSIGKILL; предыдущие версии Python молча принимали это, но 2.4 возбудит исключениеRuntimeError.В модуль
socketдобавлены две новые функции.socketpair()возвращает пару соединённых сокетов, аgetservbyport(port)ищет имя службы для заданного номера порта. (Добавлено Dave Cole и Barry Warsaw.)Функция
sys.exitfunc()объявлена устаревшей. Код должен использовать существующий модульatexit, который правильно обрабатывает вызов нескольких функций завершения. В конечном итогеsys.exitfunc()станет чисто внутренним интерфейсом, доступным только черезatexit.Модуль
tarfileтеперь по умолчанию создаёт tar-файлы в формате GNU. (Добавлено Lars Gustäbel.)Модуль
threadingтеперь имеет элегантно простой способ поддержки потоково-локальных данных. Модуль содержит классlocal, значения атрибутов которого являются локальными для разных потоков.import threading data = threading.local() data.number = 42 data.url = ('www.python.org', 80)
Другие потоки могут присваивать и получать свои собственные значения для атрибутов
numberиurl. Можно создать подклассlocalдля инициализации атрибутов или добавления методов. (Добавлено Jim Fulton.)Модуль
timeitтеперь автоматически отключает периодическую сборку мусора во время цикла замеров. Это изменение делает последовательные замеры времени более сопоставимыми. (Добавлено Raymond Hettinger.)Модуль
weakrefтеперь поддерживает более широкий спектр объектов, включая функции Python, экземпляры классов, множества, frozenset, deque, массивы, файлы, сокеты и объекты шаблонов регулярных выражений. (Добавлено Raymond Hettinger.)Модуль
xmlrpclibтеперь поддерживает расширение multi-call для передачи нескольких XML-RPC-вызовов в одной HTTP-операции. (Автор: Брайан Куинлан.)Модули
mpz,rotorиxreadlinesбыли удалены.
doctest¶
Модуль doctest подвергся существенному рефакторингу благодаря Эдварду
Лоперу и Тиму Питерсу. Тестирование по-прежнему может быть таким же простым, как запуск
doctest.testmod(), но рефакторинг позволяет настраивать работу модуля
различными способами
Новый класс DocTestFinder извлекает тесты из docstrings переданного объекта:
def f (x, y):
""">>> f(2,2)
4
>>> f(3,2)
6
"""
return x*y
finder = doctest.DocTestFinder()
# получить список экземпляров DocTest
tests = finder.find(f)
Новый класс DocTestRunner затем запускает отдельные тесты и может создать
сводку результатов:
runner = doctest.DocTestRunner()
for t in tests:
tried, failed = runner.run(t)
runner.summarize(verbose=1)
Приведённый выше пример даёт следующий вывод:
1 items passed all tests:
2 tests in f
2 tests in 1 items.
2 passed and 0 failed.
Test passed.
DocTestRunner использует экземпляр класса OutputChecker для
сравнения ожидаемого вывода с фактическим выводом. Этот класс принимает ряд
различных флагов, настраивающих его поведение; амбициозные пользователи также могут написать
полностью новый подкласс OutputChecker.
Стандартный проверяющий вывод предоставляет ряд удобных возможностей. Например,
с флагом doctest.ELLIPSIS многоточие (...) в ожидаемом выводе
соответствует любой подстроке, что упрощает адаптацию к выводам,
которые незначительно различаются:
def o (n):
""">>> o(1)
<__main__.C instance at 0x...>
>>>
"""
Другая специальная строка <BLANKLINE> соответствует пустой строке:
def p (n):
""">>> p(1)
<BLANKLINE>
>>>
"""
Ещё одна новая возможность – создание отображения вывода в стиле diff путём
указания флагов doctest.REPORT_UDIFF (unified diffs),
doctest.REPORT_CDIFF (context diffs) или doctest.REPORT_NDIFF
(delta-style). Например:
def g (n):
""">>> g(4)
здесь
есть
a
длинный
>>>"""
L = 'here is a rather lengthy list of words'.split()
for word in L[:n]:
print word
При запуске тестов вышеуказанной функции с указанием doctest.REPORT_UDIFF
вы получите следующий вывод:
**********************************************************************
File "t.py", line 15, in g
Failed example:
g(4)
Differences (unified diff with -expected +actual):
@@ -2,3 +2,3 @@
is
a
-lengthy
+rather
**********************************************************************
Изменения в сборке и C API¶Build and C API Changes
Некоторые из изменений в процессе сборки Python и в C API:
Были добавлены три новых удобных макроса для распространённых возвращаемых значений функций расширений:
Py_RETURN_NONE,Py_RETURN_TRUEиPy_RETURN_FALSE. (Автор: Бретт Кэннон.)Ещё один новый макрос
Py_CLEARуменьшает счётчик ссылок объекта obj и устанавливает obj в нулевой указатель. (Автор: Джим Фултон.)Новая функция
PyTuple_Pack(N, obj1, obj2, ..., objN)создаёт кортежи из списка аргументов переменной длины объектов Python. (Автор: Реймонд Хеттингер.)Новая функция
PyDict_Contains(d, k)реализует быстрый поиск в словаре без маскировки исключений, возникших в процессе поиска. (Автор: Реймонд Хеттингер.)Макрос Py_IS_NAN(X) возвращает 1, если его аргумент типа float или double X является NaN. (Автор: Тим Питерс.)
C-код может избежать ненужной блокировки, используя новую функцию
PyEval_ThreadsInitialized(), чтобы узнать, выполнялись ли какие-либо операции с потоками. Если эта функция возвращает false, никакие операции блокировки не требуются. (Автор: Ник Коглан.)Новая функция
PyArg_VaParseTupleAndKeywords()аналогичнаPyArg_ParseTupleAndKeywords(), но принимаетva_listвместо количества аргументов. (Автор: Грег Чепмен.)Новый флаг метода
METH_COEXISTпозволяет функции, определённой в слотах, сосуществовать сPyCFunction, имеющим то же имя. Это может вдвое сократить время доступа к такому методу, какset.__contains__(). (Автор: Реймонд Хеттингер.)Python теперь может быть собран с дополнительным профилированием самого интерпретатора, предназначенным для помощи разработчикам ядра Python. Указание
--enable-profilingсценарию configure позволит вам профилировать интерпретатор с помощью gprof, а указание ключа--with-tscвключает профилирование с использованием регистра счётчика временных меток Pentium. Обратите внимание, что ключ--with-tscназван немного неправильно, поскольку функция профилирования также работает на платформе PowerPC, хотя эта архитектура процессора не называет этот регистр «регистром TSC». (Автор: Джереми Хилтон.)Тип
tracebackobjectбыл переименован вPyTracebackObject.
Изменения, специфичные для платформ¶Port-Specific Changes
Версия для Windows теперь собирается в MSVC++ 7.1, а также в версии 6. (Автор: Мартин фон Лёвис.)
Переход на Python 2.4¶Porting to Python 2.4
В этом разделе перечислены ранее описанные изменения, которые могут потребовать изменений в коде:
Сдвиги влево и шестнадцатеричные/восьмеричные константы, которые слишком велики, больше не вызывают
FutureWarningи не возвращают значение, ограниченное 32 или 64 битами; вместо этого они возвращают длинное целое число.Целочисленные операции больше не будут вызывать
OverflowWarning. ПредупреждениеOverflowWarningисчезнет в Python 2.5.Встроенная функция
zip()иitertools.izip()теперь возвращают пустой список вместо возбуждения исключенияTypeError, если вызваны без аргументов.Сравнение экземпляров
dateиdatetime, предоставляемых модулемdatetime, больше не допускается. Два экземпляра разных классов теперь всегда будут неравными, а операции относительного сравнения (<,>) будут возбуждатьTypeError.dircache.listdir()теперь передаёт исключения вызывающему коду вместо возврата пустых списков.LexicalHandler.startDTD()раньше получал публичные и системные идентификаторы в неправильном порядке. Это исправлено; приложения, полагающиеся на неправильный порядок, необходимо исправить.fcntl.ioctl()теперь выдаёт предупреждение, если аргумент mutate опущен и это имеет значение.Модуль
tarfileтеперь по умолчанию создаёт tar-файлы в формате GNU.Ошибка при импорте модуля больше не оставляет частично инициализированный объект модуля в
sys.modules.Noneтеперь является константой; код, присваивающий новое значение имениNone, теперь вызывает синтаксическую ошибку.Функция
signals.signal()теперь возбуждает исключениеRuntimeErrorдля некоторых недопустимых значений; ранее эти ошибки проходили незамеченными. Например, больше нельзя установить обработчик на сигналSIGKILL.
Благодарности¶Acknowledgements
Автор хотел бы поблагодарить следующих людей за предложения, исправления и помощь в работе над различными черновиками этой статьи: Koray Can, Hye-Shik Chang, Michael Dyck, Raymond Hettinger, Brian Hurt, Hamish Lawson, Fredrik Lundh, Sean Reifschneider, Sadruddin Rejeb.