Что нового в 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
. Реализации типов данных множеств на языке C теперь добавлены в ядро 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, содержащий все элементы. Это неизбежно тянет все объекты в память, что может стать проблемой, если ваш набор данных очень велик. При попытке написать программу в функциональном стиле естественно было бы написать что-то вроде:
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)))
Чтобы сделать это правильно, придется немного потрудиться, но это не слишком сложно.
A small related change makes the func_name
attribute of functions
writable. This attribute is used to display function names in tracebacks, so
decorators should change the name of any new function that’s constructed and
returned.
См.также
- 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: Новый подпроцесс Модуль¶
The standard library provides a number of ways to execute a subprocess, offering
different features and different levels of complexity.
os.system(command)
is easy to use, but slow (it runs a shell process
which executes the command) and dangerous (you have to be careful about escaping
the shell’s metacharacters). The popen2
module offers classes that can
capture standard output and standard error from the subprocess, but the naming
is confusing. The subprocess
module cleans this up, providing a unified
interface that offers all the features you might need.
Instead of popen2
’s collection of classes, subprocess
contains a
single class called subprocess.Popen
whose constructor supports a number of
different keyword arguments.
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")
Внимание: бит sign является булевым значением, поэтому 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
В статье используется код на языке Фортран для иллюстрации многих проблем, которые может вызвать неточность плавающей точки.
- 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-old.gnome.org/glib/2.26/), разработчики которой любезно перелицензировали соответствующие функции и передали их в 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']
В метод списков
sort()
добавлены три ключевых слова-параметра, cmp, key и reverse. Эти параметры упрощают некоторые распространенные случаи использования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
для повышения производительности. (Внесено Раймондом Хеттингером).The
ConfigParser
classes have been enhanced slightly. Theread()
method now returns a list of the files that were successfully parsed, and theset()
method raisesTypeError
if passed a value argument that isn’t a string. (Contributed by John Belmonte and David Goodger.)Модуль
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 наибольших или наименьших значений в наборе данных без затрат на полную сортировку. (Внесено Раймондом Хеттингером.)The
httplib
module now contains constants for HTTP status codes defined in various HTTP-related RFC documents. Constants have names such asOK
,CREATED
,CONTINUE
, andMOVED_PERMANENTLY
; use pydoc to get a full list. (Contributed by Andrew Eland.)Модуль
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)]
(Предоставлено Hye-Shik Chang.)
В
itertools
также появилась функцияtee(iterator, N)
, которая возвращает N независимых итераторов, повторяющих итератор. Если 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()
. Возможные варианты применения: закладка, окно или итераторы с задержкой просмотра. (Внесено Раймондом Хеттингером.)A number of functions were added to the
locale
module, such asbind_textdomain_codeset()
to specify a particular encoding and a family ofl*gettext()
functions that return messages in the chosen encoding. (Contributed by Gustavo Niemeyer.)В функцию
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'
, которая будет заменена значением опции по умолчанию. (Внесено Грегом Уордом.)The long-term plan is to deprecate the
rfc822
module in some future Python release in favor of theemail
package. To this end, theemail.Utils.formatdate
function has been changed to make it usable as a replacement forrfc822.formatdate()
. You may want to write new e-mail processing code with this in mind. (Change implemented by Anthony Baxter.)В модуль
os
была добавлена новая функцияurandom(n)
, возвращающая строку, содержащую n байт случайных данных. Эта функция обеспечивает доступ к специфическим для платформы источникам случайности, таким как/dev/urandom
в Linux или CryptoAPI в Windows. (Внесено Тревором Перрином.)Еще одна новая функция:
os.path.lexists(path)
возвращает true, если файл, указанный path, существует, независимо от того, является ли он символической ссылкой или нет. Это отличается от существующей функцииos.path.exists(path)
, которая возвращает false, если path является символической ссылкой, указывающей на несуществующее место назначения. (Внесено Бени Чернявским.)В модуль
posix
, который лежит в основе модуляos
, была добавлена новая функцияgetsid()
. (Внесено Дж. Рейнором).Модуль
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, экземпляры классов, множества, фростенсеты, деки, массивы, файлы, сокеты и объекты шаблонов регулярных выражений. (Внесено Раймондом Хеттингером).The
xmlrpclib
module now supports a multi-call extension for transmitting multiple XML-RPC calls in a single HTTP operation. (Contributed by Brian Quinlan.)Модули
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>
>>>
"""
Еще одна новая возможность - отображение вывода в стиле diff с помощью флагов опций doctest.REPORT_UDIFF
(unified diffs), doctest.REPORT_CDIFF
(context diffs) или doctest.REPORT_NDIFF
(delta-style). Например:
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
**********************************************************************
Изменения в сборке и C API¶
Некоторые из изменений в процессе сборки Python и в API C:
Добавлены три новых удобных макроса для обычных возвращаемых значений из функций расширения:
Py_RETURN_NONE
,Py_RETURN_TRUE
иPy_RETURN_FALSE
. (Внесено Бреттом Кэнноном).Еще один новый макрос,
Py_CLEAR
, уменьшает количество ссылок на obj и устанавливает obj в нулевой указатель. (Внесено Джимом Фултоном.)Новая функция,
PyTuple_Pack(N, obj1, obj2, ..., objN)
, строит кортежи из списка аргументов переменной длины, состоящего из объектов Python. (Внесено Раймондом Хеттингером).Новая функция
PyDict_Contains(d, k)
реализует быстрый поиск по словарю без маскировки исключений, возникающих в процессе поиска. (Вклад Раймонда Хеттингера).Макрос Py_IS_NAN(X) возвращает 1, если его плавающий или двойной аргумент X является NaN. (Внесено Тимом Питерсом).
Код на языке Си может избежать ненужной блокировки, используя новую функцию
PyEval_ThreadsInitialized()
для определения того, были ли выполнены какие-либо операции с потоком. Если эта функция возвращает false, операции блокировки не нужны. (Вклад Ника Коглана.)Новая функция,
PyArg_VaParseTupleAndKeywords()
, аналогичнаPyArg_ParseTupleAndKeywords()
, но вместо нескольких аргументов принимаетva_list
. (Внесено Грегом Чепменом).Новый флаг метода,
METH_COEXIST
, позволяет функции, определенной в слотах, сосуществовать с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()
now passes exceptions to the caller instead of returning empty lists.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.