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

Что нового в Python 2.4What’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 добавлены реализации типов данных set на 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.
http://www.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 модуль подпроцесса содержит один класс с именем 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, использующий модуль подпроцесса. Настоятельно рекомендуется прочитать этот раздел PEP.

См. также

PEP 324 - подпроцесс - новый модуль для работы с процессами
Написан и реализован Питером Острандом (Peter Åstrand) при содействии Фредрика Лунда (Fredrik Lundh) и других.

PEP 327: тип данных DecimalPEP 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

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

Для многих приложений это не имеет значения. Если я строю график точек и отображаю их на мониторе, разница между 1.1 и 1.1000000000000001 слишком мала, чтобы быть заметной. Отчёты часто ограничивают вывод определённым количеством десятичных знаков, и если округлить число до двух, трёх или даже восьми знаков, ошибка никогда не проявляется. Однако для приложений, где это важно, реализация собственных арифметических процедур требует больших усилий.

Следовательно, был создан тип Decimal.

Тип DecimalThe 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")

Тип ContextThe 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
В статье используется код на Фортране для иллюстрации многих проблем, которые может вызвать неточность вычислений с плавающей запятой.
http://www2.hursley.ibm.com/decimal/
Описание представления на основе десятичной системы. Это представление предлагается в качестве стандарта и лежит в основе нового десятичного типа Python. Большая часть этого материала была написана Mike Cowlishaw, разработчиком языка Rexx.

PEP 328: Многострочные импортыPEP 328: Multi-line Imports

Одно из изменений языка – небольшое синтаксическое улучшение, направленное на упрощение импорта множества имён из модуля. В инструкции from module import names параметр 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'. Часто это происходило из-за того, что код использовал функцию atof() из библиотеки C.

Однако отказ от установки числовой локали вызывал проблемы для расширений, использующих сторонние 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 (http://library.gnome.org/devel/glib/stable/), разработчики которой любезно перелицензировали соответствующие функции и передали их Python Software Foundation. Теперь модуль locale может изменять числовую локаль, позволяя таким расширениям, как GTK+, давать правильные результаты.

См. также

PEP 331 – Преобразования чисел с плавающей запятой/строк, не зависящие от локали
Автор – Christian R. Reis, реализация – Gustavo Carneiro.

Прочие изменения языка Other Language Changes

Ниже перечислены все изменения, которые Python 2.4 вносит в ядро языка Python.

  • Добавлены декораторы для функций и методов (PEP 318).

  • Built-in set() and frozenset() types were added (PEP 218). Other new built-ins include the reversed(seq)() function (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() предоставлены Рэймондом Хеттингером.)

  • Появилась новая встроенная функция 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. (Предоставлено Ником Когланом.)

  • Функции 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. Оставшийся неполный объект модуля мог бы ввести в заблуждение последующие импорты того же модуля, заставляя их считаться успешными, что приводило к запутанным ошибкам. (Исправлено Тимом Питерсом.)

  • None теперь является константой; код, присваивающий новое значение имени None, теперь вызывает синтаксическую ошибку. (Предоставлено Рэймондом Хеттингером.)

ОптимизацииOptimizations

  • Внутренние циклы для нарезки списков и кортежей были оптимизированы и теперь работают примерно на треть быстрее. Внутренние циклы для словарей также были оптимизированы, что привело к повышению производительности keys(), values(), items(), iterkeys(), itervalues() и iteritems(). (Предоставлено Рэймондом Хеттингером.)
  • Механизм увеличения и уменьшения списков был оптимизирован по скорости и эффективности использования памяти. Добавление и извлечение элементов из списков теперь выполняется быстрее благодаря более эффективным путям выполнения и менее частому использованию системной функции realloc(). Списковые включения также выигрывают. Метод list.extend() также был оптимизирован и больше не преобразует свой аргумент во временный список перед расширением основного списка. (Предоставлено Рэймондом Хеттингером.)
  • list(), tuple(), map(), filter() и zip() теперь работают в несколько раз быстрее с аргументами, не являющимися последовательностями, которые предоставляют метод __len__(). (Предоставлено Рэймондом Хеттингером.)
  • Методы list.__getitem__(), dict.__getitem__() и dict.__contains__() теперь реализованы как объекты method_descriptor вместо объектов wrapper_descriptor. Такая форма доступа удваивает их производительность и делает их более пригодными для использования в качестве аргументов функций высшего порядка: map(mydict.__getitem__, keylist). (Предоставлено Рэймондом Хеттингером.)
  • Добавлен новый опкод LIST_APPEND, который упрощает генерируемый байт-код для списковых включений и ускоряет их примерно на треть. (Предоставлено Рэймондом Хеттингером.)
  • Оптимизатор байткода на маленьких окнах (peephole) был улучшен для создания более короткого и быстрого байткода; примечательно, что результирующий байткод стал более читаемым. (Улучшено Raymond Hettinger.)
  • Конкатенация строк в операторах вида s = s + "abc" и s += "abc" теперь выполняется более эффективно в определённых условиях. Эта оптимизация не будет присутствовать в других реализациях Python, таких как Jython, поэтому не стоит на неё полагаться; для эффективного склеивания большого количества строк по-прежнему рекомендуется использовать метод строк join(). (Предоставлено Армином Риго.)

Итог оптимизаций в версии 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, включая необязательное преобразование регистра и необязательные альтернативные алфавиты. (Предоставлено Барри Уорсо.)

  • Модуль bisect теперь имеет реализацию на C для повышения производительности. (Предоставлено Дмитрием Васильевым.)

  • Коллекции восточноазиатских кодеков 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() будет возвращать столько данных, сколько может, а последующие вызовы будут возобновлять декодирование с того места, где остановились предыдущие. (Реализовано Вальтером Дёрвальдом.)

  • Появился новый модуль 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 для повышения производительности. (Предоставлено Рэймондом Хеттингером.)

  • Классы ConfigParser были немного улучшены. Метод read() теперь возвращает список файлов, которые были успешно обработаны, а метод set() вызывает TypeError, если ему передан аргумент value, не являющийся строкой. (Предоставлено Джоном Бельмонте и Дэвидом Гуджером.)

  • Модуль curses теперь поддерживает расширение ncurses use_default_colors(). На платформах, где терминал поддерживает прозрачность, это позволяет использовать прозрачный фон. (Предоставлено Йоргом Леманом.)

  • Модуль difflib теперь включает класс HtmlDiff, который создаёт HTML-таблицу для параллельного сравнения двух версий текста. (Предоставлено Дэном Гассом.)

  • Пакет email был обновлён до версии 3.0, в которой удалены различные устаревшие API и прекращена поддержка Python версий ниже 2.3. Версия 3.0 пакета использует новый инкрементальный парсер для MIME-сообщений, доступный в модуле email.FeedParser. Новый парсер не требует чтения всего сообщения в память и не вызывает исключений, если сообщение имеет неправильный формат; вместо этого все проблемы записываются в атрибут defect сообщения. (Разработано Энтони Бакстером, Барри Уорсо, Томасом Воутерсом и другими.)

  • Модуль heapq был переписан на C. Полученное десятикратное увеличение скорости делает модуль пригодным для обработки больших объёмов данных. Кроме того, в модуле появились две новые функции nlargest() и nsmallest(), которые используют кучи для поиска N наибольших или наименьших значений в наборе данных без затрат на полную сортировку. (Предоставлено Рэймондом Хеттингером.)

  • Модуль httplib теперь содержит константы для HTTP-статусов, определённых в различных RFC-документах, связанных с HTTP. Константы имеют такие имена, как OK, CREATED, CONTINUE и MOVED_PERMANENTLY; используйте pydoc, чтобы получить полный список. (Предоставлено Эндрю Эландом.)

  • Модуль imaplib теперь поддерживает команду IMAP THREAD (предоставлено Ивом Дионом) и новые методы deleteacl() и myrights() (предоставлено Арно Мазеном).

  • Модуль itertools обзавёлся функцией groupby(iterable[, *func*])(). iterable – это объект, по которому можно итерироваться, чтобы получить поток элементов, а необязательный параметр 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() похожа на фильтр uniq в Unix, что удобно для удаления, подсчёта или поиска дубликатов:

    >>> 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 или CryptoAPI в Windows. (Автор: Trevor Perrin.)

  • Ещё одна новая функция: os.path.lexists(path)() возвращает истину, если файл, указанный в path, существует, независимо от того, является ли он символической ссылкой. Это отличается от существующей функции os.path.exists(path)(), которая возвращает ложь, если 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 также больше не является рекурсивным – благодаря огромной работе Густаво Нимейера. В рекурсивном движке регулярных выражений некоторые шаблоны приводили к потреблению большого объёма памяти в стеке 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-операции. (Автор – Brian Quinlan.)

  • Модули mpz, rotor и xreadlines удалены.

cookielib

Библиотека cookielib поддерживает обработку HTTP-куки на стороне клиента, подобно тому, как модуль Cookie поддерживает куки на стороне сервера. Куки хранятся в хранилищах (cookie jar); библиотека прозрачно сохраняет куки, предлагаемые веб-сервером, в хранилище и извлекает их оттуда при подключении к серверу. Как и в веб-браузерах, объекты политики определяют, принимать ли куки.

Для сохранения куки между сеансами предоставляются две реализации хранилищ: одна хранит куки в формате Netscape, чтобы приложения могли использовать файлы куки Mozilla или Lynx, а другая хранит куки в том же формате, что и библиотека Perl libwww.

urllib2 был изменён для взаимодействия с cookielib: HTTPCookieProcessor управляет хранилищем куки, которое используется при доступе к URL.

Этот модуль был предоставлен Джоном Дж. Ли.

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 (унифицированные diff), doctest.REPORT_CDIFF (контекстные diff) или doctest.REPORT_NDIFF (дельта-стиль). Например:

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 APIBuild and C API Changes

Некоторые из изменений в процессе сборки Python и в C API:

  • Было добавлено три новых удобных макроса для распространённых возвращаемых значений из функций расширения: Py_RETURN_NONE, Py_RETURN_TRUE и Py_RETURN_FALSE. (Автор: Brett Cannon.)
  • Ещё один новый макрос, Py_CLEAR(obj), уменьшает счётчик ссылок obj и устанавливает obj в нулевой указатель. (Автор: Jim Fulton.)
  • Новая функция PyTuple_Pack(N, obj1, obj2, ..., objN)() создаёт кортежи из списка аргументов переменной длины, состоящего из объектов Python. (Автор: Raymond Hettinger.)
  • Новая функция PyDict_Contains(d, k)() реализует быстрый поиск в словаре, не скрывая исключения, возникающие в процессе поиска. (Автор: Raymond Hettinger.)
  • Макрос Py_IS_NAN(X) возвращает 1, если его аргумент типа float или double X является NaN. (Автор: Tim Peters.)
  • Код на C может избежать ненужной блокировки, используя новую функцию PyEval_ThreadsInitialized(), чтобы определить, выполнялись ли какие-либо операции с потоками. Если эта функция возвращает false, операции блокировки не нужны. (Автор: Nick Coghlan.)
  • Новая функция PyArg_VaParseTupleAndKeywords() аналогична PyArg_ParseTupleAndKeywords(), но принимает va_list вместо нескольких аргументов. (Автор: Greg Chapman.)
  • Новый флаг метода METH_COEXISTS позволяет функции, определённой в слотах, сосуществовать с PyCFunction с тем же именем. Это может вдвое сократить время доступа к методу, такому как set.__contains__(). (Автор: Raymond Hettinger.)
  • Python теперь можно собрать с дополнительным профилированием самого интерпретатора, предназначенным в помощь разработчикам ядра Python. Передача ----enable-profiling скрипту configure позволит профилировать интерпретатор с помощью gprof, а передача ключа ----with-tsc включает профилирование с использованием регистра счётчика временных меток Pentium. Обратите внимание, что ключ ----with-tsc назван не совсем точно, поскольку функция профилирования также работает на платформе PowerPC, хотя в этой архитектуре процессора этот регистр не называют «регистром TSC». (Автор: Jeremy Hylton.)
  • Тип tracebackobject был переименован в PyTracebackObject.

Изменения, специфичные для платформPort-Specific Changes

  • Версия для Windows теперь собирается в MSVC++ 7.1, а также в версии 6. (Автор: Мартин фон Лёвис.)

Переход на Python 2.4Porting 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.