Что нового в Python 2.4¶
- Автор
А.М. Кучлинг
Эта статья рассказывает о новых возможностях в 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 Library Reference и Python Reference Manual. Часто вас будут отсылать к PEP для конкретной новой функции для объяснения реализации и обоснования дизайна.
PEP 218: Встроенные объекты множеств¶
В Python 2.3 появился модуль sets
. Реализация типов данных множеств на языке Си теперь добавлена в ядро Python в виде двух новых встроенных типов, set(iterable)
и frozenset(iterable)
. Они обеспечивают высокую скорость операций для проверки принадлежности, для удаления дубликатов из последовательностей, а также для математических операций, таких как объединения, пересечения, разности и симметричные разности.
>>> a = set('abracadabra') # form a set from a string
>>> 'z' in a # fast membership testing
False
>>> a # unique letters in a
set(['a', 'r', 'b', 'c', 'd'])
>>> ''.join(a) # convert back into a string
'arbcd'
>>> b = set('alacazam') # form a second set
>>> a - b # letters in a but not in b
set(['r', 'd', 'b'])
>>> a | b # letters in either a or b
set(['a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'])
>>> a & b # letters in both a and b
set(['a', 'c'])
>>> a ^ b # letters in a or b but not both
set(['r', 'd', 'b', 'm', 'z', 'l'])
>>> a.add('z') # add a new element
>>> a.update('wxy') # add multiple new elements
>>> a
set(['a', 'c', 'b', 'd', 'r', 'w', 'y', 'x', 'z'])
>>> a.remove('x') # take one element out
>>> a
set(['a', 'c', 'b', 'd', 'r', 'w', 'y', 'z'])
Тип frozenset()
представляет собой неизменяемую версию set()
. Поскольку он неизменяемый и хэшируемый, его можно использовать как ключ словаря или как член другого набора.
Модуль sets
остается в стандартной библиотеке и может быть полезен, если вы хотите подклассифицировать классы Set
или ImmutableSet
. В настоящее время нет планов по выводу модуля из эксплуатации.
См.также
- PEP 218 - Добавление встроенного типа объекта Set
Первоначально предложена Грегом Уилсоном и в конечном итоге реализована Раймондом Хеттингером.
PEP 237: Унификация длинных целых и целых чисел¶
Длительный процесс перехода на этот 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: Генератор выражений¶
Функция итератора, появившаяся в Python 2.2, и модуль itertools
облегчают написание программ, которые циклически просматривают большие наборы данных, не имея в памяти всего набора данных за один раз. Понимание списков не очень хорошо вписывается в эту картину, потому что оно создает объект Python list, содержащий все элементы. Это неизбежно тянет все объекты в память, что может стать проблемой, если ваш набор данных очень велик. При попытке написать программу в функциональном стиле естественно было бы написать что-то вроде:
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: Упрощенные замены строк¶
Некоторые новые классы стандартной библиотеки предоставляют альтернативный механизм подстановки переменных в строки; этот стиль подстановки может быть лучше для приложений, где неподготовленным пользователям необходимо редактировать шаблоны.
Обычным способом замены переменных по имени является оператор %
:
>>> '%(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 - более простые подстановки строк
Написана и реализована Барри Варшавом.
PEP 318: Декораторы для функций и методов¶
Python 2.2 расширил объектную модель Python, добавив статические методы и методы классов, но не расширил синтаксис Python, чтобы обеспечить новый способ определения статических методов или методов классов. Вместо этого вам нужно было написать оператор def
обычным способом и передать полученный метод в функцию staticmethod()
или classmethod()
, которая обернула бы функцию в метод нового типа. Ваш код будет выглядеть следующим образом:
class C:
def meth (cls):
...
meth = classmethod(meth) # Rebind name to wrapped-up class method
Если метод очень длинный, то легко пропустить или забыть о вызове 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 - Декораторы для функций, методов и классов
Написано Кевином Д. Смитом, Джимом Джуеттом и Скипом Монтанаро. Несколько человек написали патчи, реализующие декораторы функций, но единственным, который был действительно проверен, был патч #979728, написанный Марком Расселом.
- https://wiki.python.org/moin/PythonDecoratorLibrary
Эта страница Wiki содержит несколько примеров декораторов.
PEP 322: Обратная итерация¶
Новая встроенная функция 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 - Обратная итерация
Написана и реализована Раймондом Хеттингером.
PEP 324: Новый подпроцесс Модуль¶
Стандартная библиотека предоставляет несколько способов выполнения подпроцесса, предлагая различные возможности и различные уровни сложности. Модуль os.system(command)
прост в использовании, но медленный (он запускает процесс оболочки, который выполняет команду) и опасный (нужно быть осторожным с экранированием метасимволов оболочки). Модуль popen2
предлагает классы, которые могут перехватывать стандартный вывод и стандартную ошибку из подпроцесса, но их именование сбивает с толку. Модуль subprocess
очищает это, предоставляя единый интерфейс, который предлагает все функции, которые вам могут понадобиться.
Вместо коллекции классов popen2
, 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 universal newlines.
Создав экземпляр 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:
# Success
...
else:
# dpkg returned an error
...
Команда вызывается без использования оболочки. Если вы действительно хотите использовать оболочку, вы можете добавить shell=True
в качестве аргумента ключевого слова и указать строку вместо последовательности:
sts = subprocess.call('dpkg -i /tmp/new-package.deb', shell=True)
В PEP взяты различные примеры кода shell и Python и показано, как они будут переведены в код Python, использующий subprocess
. Настоятельно рекомендуется прочитать этот раздел PEP.
См.также
- PEP 324 - subprocess - Новый модуль процесса
Написана и реализована Петером Острандом, при содействии Фредрика Лунда и других.
PEP 327: Десятичный тип данных¶
Python всегда поддерживал в качестве типа данных числа с плавающей точкой (FP), основанные на базовом типе C double. Однако, хотя большинство языков программирования предоставляют тип с плавающей точкой, многие люди (даже программисты) не знают, что числа с плавающей точкой не могут точно представлять некоторые десятичные дроби. Новый тип Decimal
может точно представлять эти дроби, вплоть до заданного пользователем предела точности.
Зачем нужна десятичная дробь?¶
Ограничения возникают из-за представления, используемого для чисел с плавающей точкой. Числа с плавающей запятой состоят из трех компонентов:
Знак, положительный или отрицательный.
Мантисса, которая представляет собой одноразрядное двоичное число, за которым следует дробная часть. Например,
1.01
в нотации основания-2 равно1 + 0/2 + 1/4
, или 1,25 в десятичной нотации.Экспонента, которая указывает, где находится десятичная точка в представленном числе.
Например, число 1,25 имеет положительный знак, значение мантиссы 1,01 (в двоичном исчислении) и экспоненту 0 (десятичную точку не нужно сдвигать). Число 5 имеет тот же знак и мантиссу, но экспонента равна 2, потому что мантисса умножается на 4 (2 в степени экспоненты 2); 1,25 * 4 равно 5.
Современные системы обычно обеспечивают поддержку чисел с плавающей точкой, соответствующих стандарту IEEE 754. Тип Си double обычно реализуется как 64-битное число IEEE 754, которое использует 52 бита пространства для мантиссы. Это означает, что числа могут быть заданы только с точностью до 52 бит. Если вы пытаетесь представить числа, расширение которых повторяется бесконечно, то расширение обрывается после 52 бит. К сожалению, большинство программного обеспечения должно производить вывод по основанию 10, а обычные дроби по основанию 10 часто являются повторяющимися десятичными дробями в двоичном исчислении. Например, 1,1 десятичной дроби - это двоичная 1.0001100110011 ...
; .1 = 1/16 + 1/32 + 1/256 плюс бесконечное число дополнительных членов. IEEE 754 приходится отсекать эту бесконечно повторяющуюся десятичную дробь после 52 цифр, поэтому представление получается немного неточным.
Иногда эту неточность можно увидеть при печати номера:
>>> 1.1
1.1000000000000001
Неточность не всегда видна при печати числа, потому что преобразование FP в десятичную строку обеспечивается библиотекой C, а большинство библиотек C стараются выводить разумные результаты. Однако даже если она не отображается, неточность все равно присутствует, и последующие операции могут увеличить ошибку.
Для многих приложений это не имеет значения. Если я строю точки и отображаю их на мониторе, разница между 1,1 и 1,1000000000000001 слишком мала, чтобы быть заметной. Отчеты часто ограничивают вывод определенным числом знаков после запятой, и если округлить число до двух, трех или даже восьми знаков после запятой, ошибка никогда не будет заметна. Однако для приложений, где это имеет значение, требуется много работы по реализации собственных арифметических процедур.
Таким образом, был создан тип Decimal
.
Тип Decimal
¶
В стандартную библиотеку Python был добавлен новый модуль decimal
. Он содержит два класса, Decimal
и Context
. Экземпляры Decimal
представляют числа, а экземпляры Context
используются для обертывания различных настроек, таких как точность и режим округления по умолчанию.
Decimal
экземпляры неизменяемы, как обычные целые числа Python и числа FP; после их создания вы не можете изменить значение, которое представляет экземпляр. 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 - отрицательное.
Преобразование из чисел с плавающей точкой создает некоторую проблему: должно ли число FP, представляющее 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
¶
Экземпляры класса 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")
Действие по умолчанию для условий ошибки можно выбрать; модуль может либо вернуть специальное значение, такое как бесконечность или not-a-number, либо поднять исключения:
>>> 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 - десятичный тип данных
Написана Факундо Батистой и реализована Факундо Батистой, Эриком Прайсом, Раймондом Хеттингером, Аахзом и Тимом Питерсом.
- http://www.lahey.com/float.htm
В статье используется код Fortran для иллюстрации многих проблем, которые может вызвать неточность плавающей точки.
- http://speleotrove.com/decimal/
Описание десятичного представления. Это представление предлагается в качестве стандарта и лежит в основе нового десятичного типа Python. Большая часть этого материала была написана Майком Каулишоу, разработчиком языка Rexx.
PEP 328: Многолинейный импорт¶
Одно из изменений в языке - это небольшая синтаксическая правка, направленная на упрощение импорта многих имен из модуля. В операторе 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 - Импорт: Многострочный и абсолютный/относительный
Написано Аахзом. Многострочный импорт был реализован Димой Дорфманом.
PEP 331: Локально-независимые преобразования плавающей/строчной величин¶
Модуль 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 (https://developer.gnome.org/glib/stable/), разработчики которой любезно перелицензировали соответствующие функции и передали их в Python Software Foundation. Модуль locale
теперь может изменять числовую локаль, позволяя расширениям, таким как GTK+, выдавать правильные результаты.
См.также
- PEP 331 - Локально-независимые преобразования плавающей/строчной величины
Автор - Кристиан Р. Рейс, реализация - Густаво Карнейро.
Другие языковые изменения¶
Вот все изменения, которые 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
. Это включает любое отображение, любую итерацию пар ключ/значение, а также аргументы в виде ключевых слов. (Внесено Раймондом Хеттингером.)Строковые методы
ljust()
,rjust()
иcenter()
теперь принимают необязательный аргумент для указания символа заполнения, отличного от пробела. (Внесено Раймондом Хеттингером.)Строки также получили метод
rsplit()
, который работает подобно методуsplit()
, но разделяет с конца строки. (Внесено Шоном Рейфшнайдером.)>>> '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() # Case-sensitive sort >>> L ['A', 'D', 'b', 'c'] >>> # Using 'key' parameter to sort list >>> L.sort(key=lambda x: x.lower()) >>> L ['A', 'b', 'c', 'D'] >>> # Old-fashioned way >>> 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 принимает булево значение. Если значение равно true, список будет отсортирован в обратном порядке. Вместо
L.sort(); L.reverse()
теперь можно написатьL.sort(reverse=True)
.Результаты сортировки теперь гарантированно стабильны. Это означает, что две записи с одинаковыми ключами будут возвращены в том же порядке, в котором они были введены. Например, вы можете отсортировать список людей по имени, а затем отсортировать список по возрасту, в результате чего получится список, отсортированный по возрасту, в котором люди с одинаковым возрастом расположены в порядке сортировки по имени.
(Все изменения в
sort()
внесены Раймондом Хеттингером).Существует новая встроенная функция
sorted(iterable)
, которая работает как метод in-placelist.sort()
, но может использоваться в выражениях. Различия заключаются в следующем:входом может быть любая итерабельность;
вновь сформированная копия сортируется, оставляя оригинал нетронутым; и
выражение возвращает новую отсортированную копию
>>> L = [9,7,8,3,2,4,1,6,5] >>> [10+i for i in sorted(L)] # usable in a list comprehension [11, 12, 13, 14, 15, 16, 17, 18, 19] >>> L # original is left unchanged [9,7,8,3,2,4,1,6,5] >>> sorted('Monty Python') # any iterable may be an input [' ', 'M', 'P', 'h', 'n', 'n', 'o', 'o', 't', 't', 'y', 'y'] >>> # List the contents of a dict sorted by key values >>> 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
(При участии Раймонда Хеттингера.)
Операции с целыми числами больше не будут вызывать предупреждение
OverflowWarning
. ПредупреждениеOverflowWarning
исчезнет в Python 2.5.В интерпретаторе появился новый переключатель
-m
, который принимает имя, ищет соответствующий модуль наsys.path
и запускает модуль как сценарий. Например, теперь вы можете запустить профилировщик Python с помощьюpython -m profile
. (Внесено Ником Когланом.)Функции
eval(expr, globals, locals)
иexecfile(filename, globals, locals)
, а также операторexec
теперь принимают любой тип отображения для параметра locals. Ранее это должен был быть обычный словарь Python. (Внесено Раймондом Хеттингером.)Встроенная функция
zip()
иitertools.izip()
теперь возвращают пустой список, если вызываются без аргументов. Ранее они вызывали исключениеTypeError
. Это делает их более подходящими для использования со списками аргументов переменной длины:>>> def transpose(array): ... return zip(*array) ... >>> transpose([(1,2,3), (4,5,6)]) [(1, 4), (2, 5), (3, 6)] >>> transpose([]) []
(При участии Раймонда Хеттингера.)
В результате сбоя при импорте модуля больше не остается не полностью инициализированный объект модуля в
sys.modules
. Оставленный неполный объект модуля мог обмануть последующие импорты того же модуля, что приводило к запутанным ошибкам. (Исправлено Тимом Питерсом.)None
теперь является константой; код, который связывает новое значение с именемNone
, теперь является синтаксической ошибкой. (Внесено Раймондом Хеттингером.)
Оптимизации¶
Внутренние циклы для нарезки списков и кортежей были оптимизированы и теперь выполняются примерно на треть быстрее. Внутренние циклы для словарей также были оптимизированы, что привело к увеличению производительности для
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 был улучшен для получения более короткого и быстрого байткода; примечательно, что полученный байткод более читабелен. (Улучшено Раймондом Хеттингером.)
Конкатенация строк в операторах вида
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).
Новые, улучшенные и устаревшие модули¶
Как обычно, стандартная библиотека Python получила ряд улучшений и исправлений ошибок. Вот неполный список наиболее заметных изменений, отсортированный в алфавитном порядке по имени модуля. За более полным списком изменений обратитесь к файлу Misc/NEWS
в дереве исходных текстов или просмотрите журналы CVS, чтобы узнать все подробности.
Функция
asyncore
модуляloop()
теперь имеет параметр count, который позволяет выполнять ограниченное количество проходов через цикл опроса. По умолчанию цикл по-прежнему выполняется вечно.Модуль
base64
теперь имеет более полную поддержку RFC 3548 для кодирования и декодирования Base64, Base32 и Base16, включая опциональное сложение регистров и опциональные альтернативные алфавиты. (Внесено Барри Варшавом.)Модуль
bisect
теперь имеет базовую реализацию на языке C для повышения производительности. (Внесено Дмитрием Васильевым.)Коллекция восточноазиатских кодеков CJKCodecs, поддерживаемая Hye-Shik Chang, была интегрирована в 2.4. Новыми кодеками являются:
Китайский (КНР): gb2312, gbk, gb18030, big5hkscs, hz
Китайский (ROC): 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') # make a new deque with three items >>> d.append('j') # add a new entry to the right side >>> d.appendleft('f') # add a new entry to the left side >>> d # show the representation of the deque deque(['f', 'g', 'h', 'i', 'j']) >>> d.pop() # return and remove the rightmost item 'j' >>> d.popleft() # return and remove the leftmost item 'f' >>> list(d) # list the contents of the deque ['g', 'h', 'i'] >>> 'h' in d # search the deque True
Некоторые модули, такие как модули
Queue
иthreading
, теперь используют преимуществаcollections.deque
для повышения производительности. (Внесено Раймондом Хеттингером.)Классы
ConfigParser
были немного усовершенствованы. Методread()
теперь возвращает список файлов, которые были успешно разобраны, а методset()
вызывает ошибкуTypeError
, если передан аргумент значение, не являющийся строкой. (Вклад внесли Джон Белмонте и Дэвид Гуджер.)Модуль
curses
теперь поддерживает расширение ncursesuse_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()
аналогична фильтру Unixuniq
, что делает его удобным для устранения, подсчета или идентификации дублирующихся элементов:>>> word = 'abracadabra' >>> letters = sorted(word) # Turn string into a sorted list of letters >>> 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'] >>> # List unique letters >>> [k for k, g in groupby(letters)] ['a', 'b', 'c', 'd', 'r'] >>> # Count letter occurrences >>> [(k, len(list(g))) for k, g in groupby(letters)] [('a', 5), ('b', 2), ('c', 1), ('d', 1), ('r', 2)]
(При участии Хье-Шик Чанга.)
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) # Run the first iterator to exhaustion [1, 2, 3] >>> list(i2) # Run the second iterator to exhaustion [1, 2, 3]
Обратите внимание, что
tee()
должен хранить копии значений, возвращаемых итератором; в худшем случае ему может потребоваться хранить их все. Поэтому его следует использовать осторожно, если ведущий итератор может сильно опережать идущий следом итератор в длинном потоке входных данных. Если разделение велико, то вместо него лучше использоватьlist()
. Когда итераторы идут вплотную друг к другу, идеально подходитtee()
. Возможные области применения: создание закладок, окон или итераторов с опережающим просмотром. (Внесено Раймондом Хеттингером.)В модуль
locale
был добавлен ряд функций, таких какbind_textdomain_codeset()
для указания конкретной кодировки и семейство функцийl*gettext()
, возвращающих сообщения в выбранной кодировке. (Внесено Густаво Нимейером.)Для упрощения настройки журнала в функцию
logging
пакетаbasicConfig()
были добавлены некоторые ключевые аргументы. По умолчанию сообщения записываются в стандартную ошибку, но можно указать различные ключевые аргументы для записи в определенный файл, изменения формата записи или установки уровня записи. Например:import logging logging.basicConfig(filename='/var/log/application.log', level=0, # Log all messages format='%(levelname):%(process):%(thread):%(message)')
Другие дополнения к пакету
logging
включают метод удобстваlog(level, msg)
, а также классTimedRotatingFileHandler
, который поворачивает файлы журналов через заданный интервал времени. В модуле уже был классRotatingFileHandler
, который поворачивал журналы, когда файл превышал определенный размер. Оба класса происходят от нового классаBaseRotatingHandler
, который может быть использован для реализации других обработчиков ротации.(Изменения внесены Винаем Саджипом.)
Модуль
marshal
теперь разделяет интернированные строки при распаковке структуры данных. Это может уменьшить размер некоторых строк pickle, но основной эффект заключается в том, что файлы.pyc
стали значительно меньше. (Внесено Мартином фон Лёвисом.)Класс
nntplib
модуляNNTP
получил методыdescription()
иdescriptions()
для получения описаний групп новостей для одной группы или для ряда групп. (Внесено Юргеном А. Эрхардом.)В модуль
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)) # Sort list by second tuple item [('d', 1), ('c', 2), ('b', 3), ('a', 4)]
(При участии Раймонда Хеттингера.)
Модуль
optparse
был обновлен различными способами. Теперь модуль передает свои сообщения черезgettext.gettext()
, что позволяет интернационализировать справку и сообщения об ошибках Optik. Справочные сообщения для опций теперь могут включать строку'%default'
, которая будет заменена значением опции по умолчанию. (Внесено Грегом Уордом.)Долгосрочным планом является отказ от модуля
rfc822
в одном из будущих выпусков Python в пользу пакетаemail
. С этой целью функцияemail.Utils.formatdate()
была изменена, чтобы сделать ее пригодной для заменыrfc822.formatdate()
. Возможно, вы захотите написать новый код обработки электронной почты с учетом этого. (Изменение внесено Энтони Бакстером).В модуль
urandom(n)
была добавлена новая функцияos
, возвращающая строку, содержащую n байт случайных данных. Эта функция обеспечивает доступ к источникам случайных данных для конкретной платформы, таким как/dev/urandom
в Linux или CryptoAPI в Windows. (Внесено Тревором Перрином.)Еще одна новая функция:
os.path.lexists(path)
возвращает true, если файл, указанный path, существует, независимо от того, является ли он символической ссылкой или нет. Это отличается от существующей функцииos.path.exists(path)
, которая возвращает false, если path является символической ссылкой, указывающей на несуществующее место назначения. (Внесено Бени Чернявским.)В модуль
getsid()
, который лежит в основе модуляposix
, была добавлена новая функцияos
. (Внесено Дж. Рейнором.)Модуль
poplib
теперь поддерживает POP через SSL. (Внесено Гектором Уртубиа.)Модуль
profile
теперь может профилировать функции расширения языка C. (Внесено Ником Бастином.)Модуль
random
содержит новый методgetrandbits(N)
, который возвращает длинное целое число длиной N бит. Существующий методrandrange()
теперь используетgetrandbits()
там, где это необходимо, что делает генерацию произвольно больших случайных чисел более эффективной. (Внесено Раймондом Хеттингером.)Язык регулярных выражений, принятый модулем
re
, был расширен простыми условными выражениями, записанными как(?(group)A|B)
. group - это либо числовой идентификатор группы, либо имя группы, определенное с помощью(?P<group>...)
ранее в выражении. Если указанная группа совпала, то регулярное выражение A будет проверено на соответствие строке; если группа не совпала, то вместо нее будет использован шаблон B. (Внесено Густаво Нимейером.)Модуль
re
также больше не является рекурсивным, благодаря огромной работе Густаво Нимейера. В рекурсивном механизме регулярных выражений некоторые шаблоны занимают большое количество места в стеке C, и это приводило к переполнению стека. Например, если вы сопоставляли 30000-байтовую строку символовa
с выражением(a|b)+
, то на каждый символ расходовался один кадр стека. Python 2.3 пытался проверить переполнение стека и вызвать исключениеRuntimeError
, но некоторые шаблоны могли обойти проверку, и если вам не повезло, Python мог дать сегфаулт. Механизм регулярных выражений Python 2.4 может без проблем соответствовать этому шаблону.Модуль
signal
теперь более жестко проверяет параметры функцииsignal.signal()
на наличие ошибок. Например, вы не можете установить обработчик на сигналSIGKILL
; предыдущие версии Python спокойно приняли бы это, но 2.4 вызовет исключениеRuntimeError
.В модуль
socket
были добавлены две новые функции.socketpair()
возвращает пару соединенных сокетов, аgetservbyport(port)
ищет имя сервиса для заданного номера порта. (Вклад внесли Дэйв Коул и Барри Варшав.)Функция
sys.exitfunc()
была устаревшей. Код должен использовать существующий модульatexit
, который правильно обрабатывает вызов нескольких функций выхода. В конечном итогеsys.exitfunc()
станет чисто внутренним интерфейсом, доступ к которому будет осуществляться только черезatexit
.Модуль
tarfile
теперь по умолчанию генерирует tar-файлы в формате GNU. (Внесено Ларсом Густебелем.)Модуль
threading
теперь имеет элегантно простой способ поддержки потоково-локальных данных. Модуль содержит классlocal
, значения атрибутов которого локальны для разных потоков.import threading data = threading.local() data.number = 42 data.url = ('www.python.org', 80)
Другие потоки могут присваивать и получать собственные значения для атрибутов
number
иurl
. Вы можете подклассlocal
для инициализации атрибутов или добавления методов. (Внесено Джимом Фултоном.)Модуль
timeit
теперь автоматически отключает периодическую сборку мусора во время цикла тайминга. Это изменение делает последовательные тайминги более сопоставимыми. (Внесено Раймондом Хеттингером.)Модуль
weakref
теперь поддерживает более широкий спектр объектов, включая функции Python, экземпляры классов, множества, фростенсеты, деки, массивы, файлы, сокеты и объекты шаблонов регулярных выражений. (Внесено Раймондом Хеттингером.)Модуль
xmlrpclib
теперь поддерживает расширение multi-call для передачи нескольких вызовов XML-RPC в одной операции HTTP. (Внесено Брайаном Куинланом.)Модули
mpz
,rotor
иxreadlines
были удалены.
doctest¶
Модуль doctest
подвергся значительному рефакторингу благодаря Эдварду Лоперу и Тиму Питерсу. Тестирование по-прежнему может быть простым, как запуск doctest.testmod()
, но рефакторинг позволяет настраивать работу модуля различными способами
Новый класс DocTestFinder
извлекает тесты из документальных строк объекта:
def f (x, y):
""">>> f(2,2)
4
>>> f(3,2)
6
"""
return x*y
finder = doctest.DocTestFinder()
# Get list of DocTest instances
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>
>>>
"""
Еще одна новая возможность - это отображение вывода в стиле диффа путем указания флагов опций doctest.REPORT_UDIFF
(унифицированные диффы), doctest.REPORT_CDIFF
(контекстные диффы) или doctest.REPORT_NDIFF
(дельта-стиль). Например:
def g (n):
""">>> g(4)
here
is
a
lengthy
>>>"""
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
**********************************************************************
Изменения в API Build и C¶
Некоторые из изменений в процессе сборки Python и в C API:
Добавлены три новых удобных макроса для обычных возвращаемых значений из функций расширения:
Py_RETURN_NONE
,Py_RETURN_TRUE
иPy_RETURN_FALSE
. (Внесено Бреттом Кэнноном.)Еще один новый макрос, Py_CLEAR(obj), уменьшает количество ссылок на obj и устанавливает obj в нулевой указатель. (Внесено Джимом Фултоном.)
Новая функция,
PyTuple_Pack(N, obj1, obj2, ..., objN)
, конструирует кортежи из списка аргументов переменной длины, состоящего из объектов Python. (Внесено Раймондом Хеттингером.)Новая функция
PyDict_Contains(d, k)
реализует быстрый поиск по словарю без маскировки исключений, возникающих в процессе поиска. (Внесено Раймондом Хеттингером.)Макрос Py_IS_NAN(X) возвращает 1, если его аргумент X является NaN. (Внесено Тимом Питерсом.)
Код на языке Си может избежать ненужной блокировки, используя новую функцию
PyEval_ThreadsInitialized()
для определения того, были ли выполнены какие-либо операции с потоком. Если эта функция возвращает false, операции блокировки не нужны. (Внесено Ником Когланом.)Новая функция,
PyArg_VaParseTupleAndKeywords()
, аналогичнаPyArg_ParseTupleAndKeywords()
, но вместо нескольких аргументов принимаетva_list
. (Внесено Грегом Чепменом.)Новый флаг метода,
METH_COEXISTS
, позволяет функции, определенной в слотах, сосуществовать сPyCFunction
с тем же именем. Это может вдвое сократить время доступа к такому методу, какset.__contains__()
. (Внесено Раймондом Хеттингером.)Теперь Python может быть собран с дополнительным профилированием самого интерпретатора, предназначенным для помощи людям, разрабатывающим ядро Python. Предоставление
--enable-profiling
в сценарий configure позволит вам профилировать интерпретатор с помощью gprof, а предоставление переключателя--with-tsc
позволяет профилировать с помощью регистра Time-Stamp-Counter на Pentium. Обратите внимание, что переключатель--with-tsc
немного неправильно назван, потому что функция профилирования также работает на платформе PowerPC, хотя архитектура этого процессора не называет этот регистр «регистром TSC». (Внесено Джереми Хилтоном.)Тип
tracebackobject
был переименован вPyTracebackObject
.
Изменения, относящиеся к конкретному порту¶
Порт для Windows теперь собирается как под MSVC++ 7.1, так и под версией 6. (Внесено Мартином фон Лёвисом).
Перенос на 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
.
Благодарности¶
Автор хотел бы поблагодарить следующих людей за предложения, исправления и помощь в работе над различными черновиками этой статьи: Koray Can, Hye-Shik Chang, Michael Dyck, Raymond Hettinger, Brian Hurt, Hamish Lawson, Fredrik Lundh, Sean Reifschneider, Sadruddin Rejeb.