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

Что нового в Python 2.2What’s New in Python 2.2

Автор:

A.M. Kuchling

ВведениеIntroduction

Эта статья объясняет новые возможности Python 2.2.2, выпущенного 14 октября 2002 года. Python 2.2.2 – это выпуск с исправлением ошибок Python 2.2, первоначально вышедшего 21 декабря 2001 года.

Python 2.2 можно считать «релизом по наведению порядка». В нём есть несколько совершенно новых возможностей, таких как генераторы и итераторы, но большинство изменений, какими бы значительными и далеко идущими они ни были, направлены на устранение непоследовательностей и тёмных углов в дизайне языка.

Эта статья не претендует на полноценную спецификацию новых возможностей, а даёт удобный обзор. За полными подробностями обращайтесь к документации Python 2.2, например, к Справочнику по библиотеке Python и Справочному руководству Python. Если вы хотите понять полную реализацию и обоснование дизайна какого-либо изменения, обратитесь к соответствующему PEP для этой новой возможности.

PEP 252 и 253: Изменения типов и классовPEPs 252 and 253: Type and Class Changes

Самые большие и далеко идущие изменения в Python 2.2 касаются модели объектов и классов. Изменения должны быть обратно совместимы, поэтому ваш код, скорее всего, продолжит работать без изменений, но эти изменения дают потрясающие новые возможности. Перед тем как приступить к самому длинному и сложному разделу этой статьи, я дам обзор изменений и выскажу несколько замечаний.

Давным-давно я написал веб-страницу с перечнем недостатков дизайна Python. Одним из самых существенных была невозможность наследования от типов Python, реализованных на C. В частности, нельзя было наследовать встроенные типы, поэтому вы не могли просто унаследовать, скажем, списки, чтобы добавить к ним один полезный метод. Модуль UserList предоставляет класс, который поддерживает все методы списков и может быть унаследован, но существует много C-кода, который ожидает обычный список Python и не примет экземпляр UserList.

Python 2.2 исправляет это, и в процессе добавляет несколько захватывающих новых возможностей. Краткое резюме:

  • Вы можете наследовать встроенные типы, такие как списки и даже целые числа, и ваши подклассы должны работать везде, где требуется исходный тип.

  • Теперь можно определять статические методы и методы класса, в дополнение к методам экземпляра, доступным в предыдущих версиях Python.

  • Также можно автоматически вызывать методы при доступе к атрибуту экземпляра или его установке, используя новый механизм, называемый свойствами. Многие случаи использования __getattr__() можно переписать на свойства, что сделает код проще и быстрее. В качестве небольшого побочного преимущества, атрибуты теперь могут иметь докстринги.

  • Список допустимых атрибутов экземпляра можно ограничить определённым набором с помощью слотов, что позволяет защититься от опечаток и, возможно, сделать больше оптимизаций в будущих версиях Python.

Некоторые пользователи выразили обеспокоенность по поводу всех этих изменений. «Конечно, – говорят они, – новые функции интересны и позволяют делать разные трюки, которые были невозможны в предыдущих версиях Python, но они также усложняют язык». Некоторые говорят, что всегда рекомендовали Python за его простоту, и чувствуют, что эта простота теряется.

Лично я считаю, что беспокоиться не о чем. Многие новые возможности довольно эзотеричны, и вы можете писать много кода на Python, даже не подозревая о них. Написание простого класса не сложнее, чем раньше, так что вам не нужно утруждать себя их изучением или обучением, если они действительно не нужны. Некоторые очень сложные задачи, которые ранее были возможны только на C, теперь можно решать на чистом Python, и, на мой взгляд, это только к лучшему.

Я не буду пытаться охватить каждый частный случай и мелкое изменение, необходимые для работы новых функций. Вместо этого данный раздел опишет только общую картину. Смотрите раздел Связанные ссылки, «Связанные ссылки», для получения дополнительных источников информации о новой объектной модели Python 2.2.

Старые и новые классыOld and New Classes

Прежде всего, следует знать, что Python 2.2 действительно имеет два вида классов: классические (или старые) классы и классы нового стиля. Модель старых классов в точности такая же, как в более ранних версиях Python. Все новые возможности, описанные в этом разделе, применимы только к классам нового стиля. Это разделение не предполагается сохранять навсегда; в конечном итоге старые классы будут удалены, возможно, в Python 3.0.

Итак, как определить класс нового стиля? Для этого нужно унаследоваться от существующего класса нового стиля. Большинство встроенных типов Python, такие как целые числа, списки, словари и даже файлы, теперь являются классами нового стиля. Также был добавлен класс нового стиля с именем object, базовый класс для всех встроенных типов, так что если ни один встроенный тип не подходит, можно просто унаследоваться от object:

class C(object):
    def __init__ (self):
        ...
    ...

Это означает, что операторы class, не имеющие базовых классов, в Python 2.2 всегда являются классическими классами. (На самом деле это можно изменить, установив переменную уровня модуля с именем __metaclass__ – подробности см. в PEP 253 – но проще просто унаследоваться от object.)

Объекты типов для встроенных типов доступны как встроенные объекты, названные с помощью хитроумного трюка. В Python всегда были встроенные функции int(), float() и str(). В версии 2.2 они больше не являются функциями, а представляют собой объекты типов, которые ведут себя как фабрики при вызове.

>>> int
<type 'int'>
>>> int('123')
123

Для полноты набора типов были добавлены новые объекты типов, такие как dict() и file(). Вот более интересный пример: добавление метода lock() к файловым объектам:

class LockableFile(file):
    def lock (self, operation, length=0, start=0, whence=0):
        import fcntl
        return fcntl.lockf(self.fileno(), operation,
                           length, start, whence)

Сейчас устаревший модуль posixfile содержал класс, который эмулировал все методы файлового объекта и также добавлял метод lock(), но этот класс нельзя было передать внутренним функциям, ожидающим встроенный файл, что теперь возможно с нашим новым LockableFile.

ДескрипторыDescriptors

В предыдущих версиях Python не было единого способа узнать, какие атрибуты и методы поддерживаются объектом. Существовали неформальные соглашения, такие как определение атрибутов __members__ и __methods__, содержащих списки имён, но часто автор расширения или класса не утруждал себя их определением. Можно было прибегнуть к проверке __dict__ объекта, но при использовании наследования классов или произвольного хука __getattr__() это могло быть неточным.

Одна большая идея, лежащая в основе новой модели классов, заключается в формализации API для описания атрибутов объекта с помощью дескрипторов. Дескрипторы определяют значение атрибута, указывая, является ли он методом или полем. Благодаря API дескрипторов становятся возможными статические методы, методы класса, а также более экзотические конструкции.

Дескрипторы атрибутов – это объекты, которые находятся внутри объектов классов и имеют несколько собственных атрибутов:

  • __name__ – это имя атрибута.

  • __doc__ – это докстринг атрибута.

  • __get__(object) – это метод, который извлекает значение атрибута из объекта.

  • __set__(object, value) устанавливает атрибут объекта в значение.

  • __delete__(object, value) удаляет атрибут значение объекта объекта.

Например, при записи obj.x Python выполняет следующие шаги:

descriptor = obj.__class__.x
descriptor.__get__(obj)

Для методов, descriptor.__get__() возвращает временный объект, который можно вызывать, и упаковывает экземпляр и метод, который должен быть вызван на нём. Именно поэтому теперь возможны статические методы и методы класса; у них есть дескрипторы, которые упаковывают только метод, или метод и класс. Краткое объяснение этих новых видов методов: статическим методам не передаётся экземпляр, поэтому они похожи на обычные функции. Методам класса передаётся класс объекта, но не сам объект. Статические методы и методы класса определяются так:

class C(object):
    def f(arg1, arg2):
        ...
    f = staticmethod(f)

    def g(cls, arg1, arg2):
        ...
    g = classmethod(g)

Функция staticmethod() принимает функцию f() и возвращает её, упакованную в дескриптор, чтобы её можно было сохранить в объекте класса. Можно было бы ожидать специального синтаксиса для создания таких методов (def static f, defstatic f() или чего-то подобного), но такого синтаксиса пока не определено; это оставлено для будущих версий Python.

Многие новые возможности, такие как слоты (slots) и свойства (properties), также реализованы как новые виды дескрипторов, и написать класс дескриптора, делающий что-то новое, несложно. Например, можно написать класс дескриптора, который позволяет записывать предусловия и постусловия в стиле языка Eiffel для метода. Класс, использующий эту возможность, может быть определён следующим образом:

from eiffel import eiffelmethod

class C(object):
    def f(self, arg1, arg2):
        # Собственно функция
        ...
    def pre_f(self):
        # Проверить предусловия
        ...
    def post_f(self):
        # Проверить постусловия
        ...

    f = eiffelmethod(f, pre_f, post_f)

Обратите внимание, что человеку, использующему новые eiffelmethod(), не нужно ничего понимать в дескрипторах. Поэтому я считаю, что новые возможности не увеличивают базовую сложность языка. Найдётся несколько волшебников, которым нужно знать о них, чтобы написать eiffelmethod() или ZODB, или что-то ещё, но большинство пользователей просто будут писать код поверх получившихся библиотек и игнорировать детали реализации.

Множественное наследование: правило ромбаMultiple Inheritance: The Diamond Rule

Множественное наследование стало более полезным благодаря изменению правил разрешения имён. Рассмотрим следующий набор классов (диаграмма взята из PEP 253 Гвидо ван Россума):

      class A:
        ^ ^  def save(self): ...
       /   \
      /     \
     /       \
    /         \
class B     class C:
    ^         ^  def save(self): ...
     \       /
      \     /
       \   /
        \ /
      class D

Правило поиска для классических классов простое, но не очень умное: базовые классы просматриваются в глубину, слева направо. Обращение к D.save() будет искать в классах D, B, а затем A, где будет найден save() и возвращён. C.save() не будет найден вообще. Это плохо, потому что если метод save() C сохраняет некоторое внутреннее состояние, специфичное для C, то его невызов приведёт к тому, что это состояние никогда не будет сохранено.

Классы нового стиля следуют другому алгоритму, который немного сложнее объяснить, но делает правильное дело в этой ситуации. (Обратите внимание, что Python 2.3 изменяет этот алгоритм на тот, который в большинстве случаев даёт те же результаты, но даёт более полезные результаты для действительно сложных графов наследования.)

  1. Перечислить все базовые классы, следуя классическому правилу поиска, и включать класс несколько раз, если он посещается повторно. В приведённом примере список посещённых классов: [D, B, A, C, A].

  2. Проверить список на наличие дублирующихся классов. Если таковые найдены, удалить все вхождения, кроме одного, оставив последнее в списке. В приведённом примере список становится [D, B, C, A] после удаления дубликатов.

Следуя этому правилу, обращение к D.save() вернёт C.save(), что и является нужным поведением. Это правило поиска совпадает с правилом, используемым в Common Lisp. Новая встроенная функция super() предоставляет способ получить суперклассы класса без необходимости повторной реализации алгоритма Python. Наиболее часто используемой формой будет super(class, obj), которая возвращает связанный объект суперкласса (не сам объект класса). Эта форма будет использоваться в методах для вызова метода суперкласса; например, метод save() D будет выглядеть следующим образом:

class D (B,C):
    def save (self):
        # Вызвать .save() родительского класса
        super(D, self).save()
        # Сохранить приватные данные D здесь
        ...

super() также может возвращать несвязанные объекты суперкласса при вызове как super(class) или super(class1, class2), но это, вероятно, не будет часто полезно.

Доступ к атрибутамAttribute Access

Немало сложных классов Python определяют перехватчики для доступа к атрибутам с помощью __getattr__(); чаще всего это делается для удобства, чтобы сделать код более читаемым за счёт автоматического преобразования доступа к атрибуту, такого как obj.parent, в вызов метода, такой как obj.get_parent. Python 2.2 добавляет несколько новых способов управления доступом к атрибутам.

Во-первых, __getattr__(attr_name) по-прежнему поддерживается классами нового стиля, и в нём ничего не изменилось. Как и прежде, он будет вызываться при попытке доступа к obj.foo, если в словаре экземпляра не найден атрибут с именем foo.

Классы нового стиля также поддерживают новый метод – __getattribute__(attr_name). Разница между двумя методами в том, что __getattribute__() вызывается всегда при любом доступе к атрибуту, тогда как старый __getattr__() вызывается только если foo не найден в словаре экземпляра.

Однако поддержка свойств (properties) в Python 2.2 часто будет более простым способом перехвата обращений к атрибутам. Написание метода __getattr__() – дело сложное, потому что для избежания рекурсии внутри него нельзя использовать обычные обращения к атрибутам, и вместо этого приходится работать с содержимым __dict__. Методы __getattr__() также вызываются Python при проверке других методов, таких как __repr__() или __coerce__(), поэтому их нужно писать с учётом этого. Наконец, вызов функции при каждом доступе к атрибуту приводит к существенному снижению производительности.

property – это новый встроенный тип, который объединяет три функции: получения, установки или удаления атрибута, а также строку документации. Например, если требуется определить атрибут size, который вычисляется, но также может быть установлен, можно написать:

class C(object):
    def get_size (self):
        result = ... computation ...
        return result
    def set_size (self, size):
        ... compute something based on the size
        and set internal state appropriately ...

    # Определить свойство. Метод 'delete this attribute'
    # метод определён как None, поэтому атрибут
    # не может быть удалён.
    size = property(get_size, set_size,
                    None,
                    "Storage size of this instance")

Это, безусловно, понятнее и проще в написании, чем пара методов __getattr__()/__setattr__(), которые проверяют атрибут size и обрабатывают его особым образом, извлекая все остальные атрибуты из __dict__ экземпляра. Кроме того, доступ к size – единственный, который требует вызова функции, поэтому обращения к другим атрибутам выполняются на обычной скорости.

Наконец, можно ограничить список атрибутов, к которым можно обращаться у объекта, с помощью нового атрибута класса __slots__. Объекты Python обычно очень динамичны; в любой момент можно определить новый атрибут у экземпляра, просто написав obj.new_attr=1. Класс нового стиля может определить атрибут класса с именем __slots__, чтобы ограничить допустимые атрибуты определённым набором имён. Пример прояснит это:

>>> class C(object):
...     __slots__ = ('template', 'name')
...
>>> obj = C()
>>> print obj.template
None
>>> obj.template = 'Test'
>>> print obj.template
Test
>>> obj.newattr = None
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AttributeError: 'C' object has no attribute 'newattr'

Обратите внимание, что при попытке присвоить значение атрибуту, не указанному в __slots__, возникает AttributeError.

PEP 234: ИтераторыPEP 234: Iterators

Ещё одно значительное дополнение в 2.2 – это интерфейс итерации на уровнях C и Python. Объекты могут определять, как по ним можно итерироваться вызывающим кодом.

В версиях Python до 2.1 обычным способом заставить for item in obj работать было определение метода __getitem__(), который выглядел примерно так:

def __getitem__(self, index):
    return <next item>

__getitem__() правильнее использовать для определения операции индексирования объекта, чтобы можно было писать obj[5] для получения шестого элемента. Это немного сбивает с толку, когда вы используете это только для поддержки циклов for. Рассмотрим некий файлоподобный объект, по которому нужно итерироваться; параметр index по сути бессмысленен, так как класс, вероятно, предполагает, что будет сделана серия вызовов __getitem__() с увеличивающимся на единицу index. Другими словами, наличие метода __getitem__() не означает, что использование file[5] для произвольного доступа к шестому элементу сработает, хотя на самом деле должно.

В Python 2.2 итерацию можно реализовать отдельно, а методы __getitem__() можно ограничить классами, которые действительно поддерживают произвольный доступ. Основная идея итераторов проста. Новая встроенная функция iter(obj) или iter(C, sentinel) используется для получения итератора. iter(obj) возвращает итератор для объекта obj, а iter(C, sentinel) возвращает итератор, который будет вызывать вызываемый объект C до тех пор, пока он не вернёт sentinel, сигнализируя об окончании итератора.

Классы Python могут определять метод __iter__(), который должен создавать и возвращать новый итератор для объекта; если объект сам является своим итератором, этот метод может просто вернуть self. В частности, итераторы обычно являются собственными итераторами. Расширения, реализованные на C, могут реализовать функцию tp_iter для возврата итератора, а расширения, которые хотят вести себя как итераторы, могут определить функцию tp_iternext.

Итак, что же на самом деле делают итераторы? У них есть один обязательный метод next(), который не принимает аргументов и возвращает следующее значение. Когда больше нечего возвращать, вызов next() должен возбуждать исключение StopIteration.

>>> L = [1,2,3]
>>> i = iter(L)
>>> print i
<iterator object at 0x8116870>
>>> i.next()
1
>>> i.next()
2
>>> i.next()
3
>>> i.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
StopIteration
>>>

В Python 2.2 оператор for больше не требует последовательности; он ожидает объект, для которого iter() вернёт итератор. Для обратной совместимости и удобства итератор автоматически создаётся для последовательностей, которые не реализуют __iter__() или слот tp_iter, так что for i in [1,2,3] по-прежнему будет работать. Везде, где интерпретатор Python выполняет цикл по последовательности, он теперь использует протокол итератора. Это означает, что можно делать, например, следующее:

>>> L = [1,2,3]
>>> i = iter(L)
>>> a,b,c = i
>>> a,b,c
(1, 2, 3)

Поддержка итераторов была добавлена для некоторых базовых типов Python. Вызов iter() для словаря вернёт итератор, который перебирает его ключи:

>>> m = {'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6,
...      'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12}
>>> for key in m: print key, m[key]
...
Mar 3
Feb 2
Aug 8
Sep 9
May 5
Jun 6
Jul 7
Jan 1
Apr 4
Nov 11
Dec 12
Oct 10

Это поведение по умолчанию. Если нужно перебрать ключи, значения или пары ключ/значение, можно явно вызвать методы iterkeys(), itervalues() или iteritems(), чтобы получить соответствующий итератор. В связанном небольшом изменении оператор in теперь работает со словарями, так что key in dict теперь эквивалентно dict.has_key(key).

Файлы также предоставляют итератор, который вызывает метод readline(), пока в файле есть строки. Это означает, что теперь можно читать каждую строку файла с помощью такого кода:

for line in file:
    # сделать что-то для каждой строки
    ...

Обратите внимание, что итератор можно перемещать только вперёд; нет способа получить предыдущий элемент, сбросить итератор или сделать его копию. Объект-итератор может предоставлять такие дополнительные возможности, но протокол итератора требует только метод next().

См. также

PEP 234 – Итераторы

Авторы: Ка-Пинг Йи и Гвидо ван Россум; реализовано командой Python Labs, в основном Гвидо и Тимом Петерсом.

PEP 255: Простые генераторыPEP 255: Simple Generators

Генераторы – ещё одна новая возможность, которая связана с введением итераторов.

Вы, несомненно, знакомы с тем, как работают вызовы функций в Python или C. Когда вызывается функция, она получает отдельное пространство имён, в котором создаются её локальные переменные. Когда функция достигает оператора return, локальные переменные уничтожаются, а полученное значение возвращается вызывающему. Последующий вызов той же функции получит новый набор локальных переменных. Но что, если бы локальные переменные не уничтожались при выходе из функции? Что, если бы можно было возобновить выполнение функции с того места, где она остановилась? Это и обеспечивают генераторы; их можно рассматривать как возобновляемые функции.

Вот простейший пример функции-генератора:

def generate_ints(N):
    for i in range(N):
        yield i

Для генераторов было введено новое ключевое слово yield. Любая функция, содержащая оператор yield, является генераторной функцией; это обнаруживается байт-код-компилятором Python, который компилирует такую функцию особым образом. Поскольку было введено новое ключевое слово, генераторы должны быть явно включены в модуле с помощью оператора from __future__ import generators в начале исходного кода модуля. В Python 2.3 этот оператор станет ненужным.

При вызове генераторной функции она возвращает не одно значение, а объект-генератор, поддерживающий протокол итератора. При выполнении оператора yield генератор выдаёт значение i, подобно оператору return. Большая разница между yield и оператором return заключается в том, что при достижении yield состояние выполнения генератора приостанавливается, а локальные переменные сохраняются. При следующем вызове метода next() генератора функция возобновляет выполнение сразу после оператора yield. (По сложным причинам оператор yield не допускается внутри блока try оператора tryfinally; прочтите PEP 255 для полного объяснения взаимодействия между yield и исключениями.)

Вот пример использования генератора generate_ints():

>>> gen = generate_ints(3)
>>> gen
<generator object at 0x8117f90>
>>> gen.next()
0
>>> gen.next()
1
>>> gen.next()
2
>>> gen.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 2, in generate_ints
StopIteration

Можно также написать for i in generate_ints(5) или a,b,c = generate_ints(3).

Внутри генераторной функции оператор return может использоваться только без значения и сигнализирует об окончании последовательности значений; после этого генератор не может вернуть никаких дополнительных значений. return со значением, например return 5, является синтаксической ошибкой внутри генераторной функции. Конец результатов генератора также можно указать вручную, возбудив StopIteration, или просто позволив потоку выполнения дойти до конца функции.

Эффекта генераторов можно добиться вручную, написав собственный класс и сохранив все локальные переменные генератора как переменные экземпляра. Например, возврат списка целых чисел можно было бы реализовать, установив self.count в 0 и заставив метод next() увеличивать self.count и возвращать его. Однако для сколь-нибудь сложного генератора написание соответствующего класса было бы гораздо более запутанным. Lib/test/test_generators.py содержит ряд более интересных примеров. Самый простой из них реализует симметричный обход дерева с помощью рекурсивных генераторов.

# Рекурсивный генератор, порождающий листья дерева в порядке in-order.
def inorder(t):
    if t:
        for x in inorder(t.left):
            yield x
        yield t.label
        for x in inorder(t.right):
            yield x

Два других примера в Lib/test/test_generators.py дают решения задачи о N ферзях (размещение N ферзей на шахматной доске N×N так, чтобы ни один ферзь не угрожал другому) и задачи об обходе коня (маршрут, по которому конь посещает каждую клетку доски N×N, не посещая ни одну клетку дважды).

Идея генераторов пришла из других языков программирования, особенно Icon (https://www2.cs.arizona.edu/icon/), где идея генераторов является центральной. В Icon каждое выражение и вызов функции ведут себя как генератор. Один пример из «Обзора языка программирования Icon» по адресу https://www2.cs.arizona.edu/icon/docs/ipd266.htm даёт представление о том, как это выглядит:

sentence := "Store it in the neighboring harbor"
if (i := find("or", sentence)) > 5 then write(i)

В Icon функция find() возвращает индексы, по которым найдена подстрока «or»: 3, 23, 33. В операторе if переменной i сначала присваивается значение 3, но 3 меньше 5, поэтому сравнение не удаётся, и Icon повторяет попытку со вторым значением 23. 23 больше 5, поэтому теперь сравнение успешно, и код выводит на экран значение 23.

Python не заходит так далеко, как Icon, в принятии генераторов в качестве центральной концепции. Генераторы считаются новой частью ядра языка Python, но их изучение или использование не является обязательным; если они не решают ваших задач, можете их игнорировать. Одной из новых особенностей интерфейса Python по сравнению с Icon является то, что состояние генератора представляется как конкретный объект (итератор), который можно передавать другим функциям или хранить в структуре данных.

См. также

PEP 255 - Simple Generators

Авторы: Нил Шеменауэр, Тим Питерс, Магнус Ли Хетланд. Реализовано в основном Нилом Шеменауэром и Тимом Питерсом, с дополнительными исправлениями от команды Python Labs.

PEP 237: Унификация длинных целых и целых чиселPEP 237: Unifying Long Integers and Integers

В последних версиях различие между обычными целыми (32-битными на большинстве машин) и длинными целыми (произвольного размера) стало раздражать. Например, на платформах, поддерживающих файлы размером более 2**32 байт, метод tell() файловых объектов должен возвращать длинное целое. Однако некоторые части Python ожидали обычные целые и выдавали ошибку, если вместо них передавалось длинное целое. Например, в Python 1.5 в качестве индекса среза можно было использовать только обычные целые, и 'abc'[1L:] вызывало исключение TypeError с сообщением 'slice index must be int'.

Python 2.2 будет автоматически преобразовывать короткие целые в длинные по мере необходимости. Суффикс «L» больше не нужен для обозначения литерала длинного целого, так как компилятор теперь сам выбирает подходящий тип. (Использование суффикса «L» будет не рекомендоваться в будущих версиях Python 2.x, вызывая предупреждение в Python 2.4, и, вероятно, удалено в Python 3.0.) Многие операции, которые раньше вызывали OverflowError, теперь будут возвращать длинное целое. Например:

>>> 1234567890123
1234567890123L
>>> 2 ** 64
18446744073709551616L

В большинстве случаев целые и длинные целые теперь обрабатываются одинаково. Вы всё ещё можете различать их с помощью встроенной функции type(), но это редко требуется.

См. также

PEP 237 – Унификация длинных целых и целых чисел

Авторы: Моше Задка и Гвидо ван Россум. В основном реализовано Гвидо ван Россумом.

PEP 238: Изменение оператора деленияPEP 238: Changing the Division Operator

Самое противоречивое изменение в Python 2.2 знаменует начало усилий по исправлению старого проектного недостатка, существовавшего в Python с самого начала. В настоящее время оператор деления Python, /, ведёт себя как оператор деления в C, когда оба операнда целые: он возвращает целочисленный результат, усечённый вниз при наличии дробной части. Например, 3/2 равно 1, а не 1,5, и (-1)/2 равно -1, а не -0,5. Это означает, что результаты деления могут неожиданно различаться в зависимости от типа двух операндов, а из-за динамической типизации Python бывает трудно определить возможные типы операндов.

(Споры ведутся о том, является ли это действительно проектным недостатком и стоит ли ломать существующий код для его исправления. Это вызвало бесконечные обсуждения в python-dev, а в июле 2001 года вылилось в шквал едко-саркастических сообщений в comp.lang.python. Я не буду выступать ни за одну из сторон и ограничусь описанием того, что реализовано в 2.2. Прочтите PEP 238 для сводки аргументов и контраргументов.)

Поскольку это изменение может нарушить работу существующего кода, его внедряют очень постепенно. Переход начинается в Python 2.2, но полное переключение произойдёт только в Python 3.0.

Сначала я позаимствую несколько терминов из PEP 238. «Истинное деление» – это деление, знакомое большинству не-программистов: 3/2 равно 1,5, 1/4 равно 0,25 и так далее. «Деление с округлением вниз» (floor division) – это то, что оператор / в Python сейчас делает с целочисленными операндами; результат – это округлённое вниз значение, возвращаемое истинным делением. «Классическое деление» – это текущее смешанное поведение /; оно возвращает результат деления с округлением вниз, когда операнды – целые числа, и результат истинного деления, когда один из операндов – число с плавающей запятой.

Вот изменения, которые вводит Python 2.2:

  • Новый оператор // – это оператор деления с округлением вниз. (Да, мы знаем, что он похож на символ комментария в C++.) // всегда выполняет деление с округлением вниз независимо от типов операндов, поэтому 1 // 2 равно 0, а 1.0 // 2.0 также равно 0,0.

    // всегда доступен в Python 2.2; его не нужно включать с помощью оператора __future__.

  • Если включить from __future__ import division в модуль, оператор / будет изменён так, чтобы возвращать результат истинного деления, поэтому 1/2 станет равно 0,5. Без оператора __future__ / по-прежнему означает классическое деление. Значение по умолчанию / не изменится до Python 3.0.

  • Классы могут определять методы с именами __truediv__() и __floordiv__() для перегрузки двух операторов деления. На уровне C также есть слоты в структуре PyNumberMethods, чтобы типы-расширения могли определять эти операторы.

  • Python 2.2 поддерживает несколько аргументов командной строки для проверки, будет ли код работать с изменённой семантикой деления. Запуск python с флагом -Q warn будет вызывать предупреждение каждый раз, когда деление применяется к двум целым числам. Это можно использовать, чтобы найти код, на который повлияло изменение, и исправить его. По умолчанию Python 2.2 просто выполняет классическое деление без предупреждения; предупреждение будет включено по умолчанию в Python 2.3.

См. также

PEP 238 – Изменение оператора деления

Написан Моше Задкой и Гвидо ван Россумом. Реализован Гвидо ван Россумом.

Изменения в поддержке UnicodeUnicode Changes

Поддержка Unicode в Python 2.2 была немного расширена. Строки Unicode обычно хранятся как UCS-2, то есть 16-битные целые числа без знака. Python 2.2 также можно скомпилировать с использованием UCS-4 (32-битные целые числа без знака) в качестве внутренней кодировки, передав --enable-unicode=ucs4 скрипту configure. (Также можно указать --disable-unicode, чтобы полностью отключить поддержку Unicode.)

При компиляции для использования UCS-4 («широкий Python») интерпретатор может напрямую работать с символами Unicode от U+000000 до U+110000, поэтому диапазон допустимых значений для функции unichr() соответственно расширяется. При использовании интерпретатора, скомпилированного для UCS-2 («узкий Python»), значения больше 65535 по-прежнему будут заставлять unichr() вызывать исключение ValueError. Всё это описано в PEP 261, «Поддержка «широких» символов Unicode»; обратитесь к нему за подробностями.

Ещё одно изменение объяснить проще. С момента появления строки Unicode поддерживали метод encode() для преобразования строки в выбранную кодировку, например UTF-8 или Latin-1. В Python 2.2 для 8-битных строк (но не для строк Unicode) был добавлен симметричный метод decode([*encoding*]). decode() предполагает, что строка находится в указанной кодировке, и декодирует её, возвращая то, что возвращает кодек.

С помощью этой новой функции были добавлены кодеки для задач, не связанных напрямую с Unicode. Например, добавлены кодеки для uu-кодирования, кодирования base64 из MIME и сжатия с помощью модуля zlib:

>>> s = """Here is a lengthy piece of redundant, overly verbose,
... and repetitive text.
... """
>>> data = s.encode('zlib')
>>> data
'x\x9c\r\xc9\xc1\r\x80 \x10\x04\xc0?Ul...'
>>> data.decode('zlib')
'Here is a lengthy piece of redundant, overly verbose,\nand repetitive text.\n'
>>> print s.encode('uu')
begin 666 <data>
M2&5R92!I<R!A(&QE;F=T:'D@<&EE8V4@;V8@<F5D=6YD86YT+"!O=F5R;'D@
>=F5R8F]S92P*86YD(')E<&5T:71I=F4@=&5X="X*

end
>>> "sheesh".encode('rot-13')
'furrfu'

Для преобразования экземпляра класса в Unicode класс может определить метод __unicode__(), аналогичный __str__().

encode(), decode() и __unicode__() были реализованы Марком-Андре Лембургом. Изменения для поддержки UCS-4 внутри были реализованы Фредриком Лундом и Мартином фон Лёвисом.

См. также

PEP 261 – Поддержка «широких» символов Unicode

Автор: Paul Prescod.

PEP 227: Вложенные области видимостиPEP 227: Nested Scopes

В Python 2.1 статически вложенные области видимости были добавлены как опциональная возможность, которую нужно было включать директивой from __future__ import nested_scopes. В Python 2.2 вложенные области видимости больше не нужно специально включать; теперь они присутствуют всегда. Остальная часть этого раздела – копия описания вложенных областей видимости из моего документа «Что нового в Python 2.1»; если вы читали его, когда вышла версия 2.1, можете пропустить оставшуюся часть.

Самое большое изменение, введённое в Python 2.1 и завершённое в 2.2, касается правил областей видимости Python. В Python 2.0 в любой момент времени для поиска имён переменных использовалось не более трёх пространств имён: локальное, модульное и встроенное. Это часто удивляло людей, потому что не соответствовало их интуитивным ожиданиям. Например, вложенное рекурсивное определение функции не работает:

def f():
    ...
    def g(value):
        ...
        return g(value-1) + 1
    ...

Функция g() всегда будет вызывать исключение NameError, потому что привязка имени g не находится ни в её локальном пространстве имён, ни в пространстве имён модуля. На практике это не такая уж большая проблема (подобные рекурсивные внутренние функции встречаются редко), но это также сделало использование выражения lambda более громоздким, и это было проблемой на практике. В коде, использующем lambda, часто можно встретить копирование локальных переменных путём передачи их в качестве значений аргументов по умолчанию.

def find(self, name):
    "Return list of any entries equal to 'name'"
    L = filter(lambda x, name=name: x == name,
               self.list_attribute)
    return L

В результате удобочитаемость кода Python, написанного в сильно функциональном стиле, сильно страдает.

Самое важное изменение в Python 2.2 – это добавление в язык статической области видимости для решения этой проблемы. Первый эффект: аргумент по умолчанию name=name теперь не нужен в приведённом выше примере. Проще говоря, если имя переменной не получает значение внутри функции (присваиванием, операторами def, class или import), ссылки на эту переменную будут искаться в локальном пространстве имён окружающей области видимости. Более подробное объяснение правил и разбор реализации можно найти в PEP.

Это изменение может вызвать некоторые проблемы совместимости для кода, где одно и то же имя переменной используется как на уровне модуля, так и в качестве локальной переменной внутри функции, содержащей другие определения функций. Однако это кажется маловероятным, поскольку такой код и без того был бы довольно запутанным для чтения.

Одним из побочных эффектов изменения является то, что операторы from module import * и exec стали недопустимыми в области видимости функции при определённых условиях. Справочное руководство Python всегда утверждало, что from module import * допустим только на верхнем уровне модуля, но интерпретатор CPython никогда раньше этого не соблюдал. В рамках реализации вложенных областей видимости компилятор, преобразующий исходный код Python в байт-код, должен генерировать разный код для доступа к переменным в охватывающей области видимости. from module import * и exec делают невозможным для компилятора определить это, поскольку они добавляют в локальное пространство имён имена, которые невозможно узнать на этапе компиляции. Поэтому, если функция содержит определения функций или выражения lambda со свободными переменными, компилятор укажет на это, вызвав исключение SyntaxError.

Чтобы сделать предыдущее объяснение немного понятнее, вот пример:

x = 1
def f():
    # Следующая строка – синтаксическая ошибка
    exec 'x=2'
    def g():
        return x

Строка 4, содержащая оператор exec, является синтаксической ошибкой, поскольку exec определил бы новую локальную переменную с именем x, значение которой должно быть доступно через g().

Это не должно быть большим ограничением, поскольку exec редко используется в большинстве кода Python (а когда используется, это часто признак плохого дизайна).

См. также

PEP 227 – Статически вложенные области видимости

Написан и реализован Джереми Хилтоном.

Новые и улучшенные модулиNew and Improved Modules

  • Модуль xmlrpclib был добавлен в стандартную библиотеку Фредриком Лундом; он предоставляет поддержку для написания XML-RPC клиентов. XML-RPC – это простой протокол удалённого вызова процедур, построенный на основе HTTP и XML. Например, следующий фрагмент получает список RSS-каналов от O’Reilly Network, а затем выводит последние заголовки для одного канала:

    import xmlrpclib
    s = xmlrpclib.Server(
          'http://www.oreillynet.com/meerkat/xml-rpc/server.php')
    channels = s.meerkat.getChannels()
    # channels – это список словарей, например:
    # [{'id': 4, 'title': 'Freshmeat Daily News'}
    #  {'id': 190, 'title': '32Bits Online'},
    #  {'id': 4549, 'title': '3DGamers'}, ... ]
    
    # Получить элементы для одного канала
    items = s.meerkat.getItems( {'channel': 4} )
    
    # 'items' – это ещё один список словарей, например:
    # [{'link': 'http://freshmeat.net/releases/52719/',
    #   'description': 'Утилита, которая преобразует HTML в XSL FO.',
    #   {'title': 'html2fo 0.3 (По умолчанию)'}
    

    Модуль SimpleXMLRPCServer упрощает создание простых XML-RPC серверов. Подробнее об XML-RPC см. http://xmlrpc.scripting.com/.

  • Новый модуль hmac реализует алгоритм HMAC, описанный в RFC 2104. (Автор: Gerhard Häring.)

  • Некоторые функции, которые раньше возвращали длинные кортежи, теперь возвращают псевдопоследовательности, которые по-прежнему ведут себя как кортежи, но также имеют мнемонические атрибуты, такие как memberst_mtime или tm_year. Улучшенные функции включают stat(), fstat(), statvfs() и fstatvfs() в модуле os, а также localtime(), gmtime() и strptime() в модуле time.

    Например, чтобы получить размер файла с помощью старых кортежей, пришлось бы писать что-то вроде file_size = os.stat(filename)[stat.ST_SIZE], но теперь это можно написать более наглядно как file_size = os.stat(filename).st_size.

    Оригинальный патч для этой функции был предоставлен Ником Мэтьюсоном.

  • Профилировщик Python был значительно переработан, и исправлены различные ошибки в его выводе. (Авторы: Фред Л. Дрейк-мл. и Тим Питерс.)

  • Модуль socket может быть скомпилирован с поддержкой IPv6; укажите опцию --enable-ipv6 в скрипте configure Python. (Автор: Jun-ichiro “itojun” Hagino.)

  • В модуль struct были добавлены два новых символа формата для 64-битных целых чисел на платформах, поддерживающих тип C long long. q – для знакового 64-битного целого, а Q – для беззнакового. Значение возвращается в длинном целом типе Python. (Автор: Тим Питерс.)

  • В интерактивном режиме интерпретатора появилась новая встроенная функция help(), которая использует модуль pydoc, представленный в Python 2.1, для организации интерактивной справки. help(object) выводит любую доступную справку об объекте. help() без аргументов запускает утилиту онлайн-справки, где можно вводить имена функций, классов или модулей для чтения их справки. (Автор: Гвидо ван Россум, с использованием модуля Ka-Ping Yee pydoc.)

  • В движок SRE, лежащий в основе модуля re, внесены различные исправления ошибок и улучшения производительности. Например, функции re.sub() и re.split() были переписаны на C. Ещё один патч ускоряет некоторые диапазоны символов Unicode в два раза, а также появился новый finditer() метод, возвращающий итератор по всем непересекающимся совпадениям в заданной строке. (SRE поддерживается Фредриком Лундом. Патч BIGCHARSET предоставлен Мартином фон Лёвисом.)

  • Модуль smtplib теперь поддерживает RFC 2487, «Безопасный SMTP через TLS», так что теперь можно шифровать трафик SMTP между программой на Python и агентом передачи почты, которому передаётся сообщение. smtplib также поддерживает аутентификацию SMTP. (Автор: Gerhard Häring.)

  • Модуль imaplib, поддерживаемый Пирсом Лодером, получил поддержку нескольких новых расширений: расширение NAMESPACE, определённое в RFC 2342, SORT, GETACL и SETACL. (Авторы: Энтони Бакстер и Мишель Пеллетье.)

  • Разбор адресов электронной почты в модуле rfc822 теперь соответствует RFC 2822, обновлению RFC 822. (Имя модуля не будет изменено на rfc2822.) Также добавлен новый пакет, email, для разбора и создания сообщений электронной почты. (Автор: Барри Варшава, работа выросла из его работы над Mailman.)

  • Модуль difflib теперь содержит новый класс Differ для создания читаемых списков изменений («дельты») между двумя последовательностями строк текста. Также появились две функции-генератора, ndiff() и restore(), которые возвращают дельту из двух последовательностей или одну из исходных последовательностей из дельты. (Черновая работа выполнена Дэвидом Гуджером, на основе кода ndiff.py Тима Питерса, который затем выполнил генераторизацию.)

  • Новые константы ascii_letters, ascii_lowercase и ascii_uppercase были добавлены в модуль string. Некоторые модули в стандартной библиотеке использовали string.letters для обозначения диапазонов A-Za-z, но это предположение неверно при использовании локалей, потому что string.letters изменяется в зависимости от набора допустимых символов, определённых текущей локалью. Все ошибочные модули были исправлены для использования ascii_letters вместо этого. (Сообщено неизвестным лицом; исправлено Фредом Л. Дрейком-мл.)

  • Модуль mimetypes теперь упрощает использование альтернативных баз данных MIME-типов за счёт добавления класса MimeTypes, который принимает список имён файлов для разбора. (Автор: Фред Л. Дрейк-мл.)

  • Класс Timer был добавлен в модуль threading, который позволяет планировать выполнение действия в будущем. (Автор: Итамар Штуль-Трауринг.)

Изменения и исправления в интерпретатореInterpreter Changes and Fixes

Некоторые изменения затрагивают только тех, кто работает с интерпретатором Python на уровне C, – тех, кто пишет модули расширения Python, встраивает интерпретатор или просто взламывает сам интерпретатор. Если вы пишете только код на Python, то описанные здесь изменения вас почти не затронут.

  • Функции профилирования и трассировки теперь могут быть реализованы на C, что позволяет работать гораздо быстрее, чем функции на Python, и должно снизить накладные расходы профилирования и трассировки. Это будет интересно авторам сред разработки для Python. В API Python были добавлены две новые функции на C, PyEval_SetProfile() и PyEval_SetTrace(). Существующие функции sys.setprofile() и sys.settrace() по-прежнему существуют и просто были изменены для использования нового интерфейса на уровне C. (Автор: Фред Л. Дрейк-мл.)

  • Был добавлен ещё один низкоуровневый API, представляющий интерес в первую очередь для разработчиков отладчиков Python и инструментов разработки. PyInterpreterState_Head() и PyInterpreterState_Next() позволяют вызывающему коду просматривать все существующие объекты интерпретатора; PyInterpreterState_ThreadHead() и PyThreadState_Next() позволяют перебирать все состояния потоков для заданного интерпретатора. (Автор: Дэвид Бизли.)

  • Интерфейс сборщика мусора на уровне C был изменён, чтобы упростить написание типов расширений, поддерживающих сборку мусора, и отладку неправильного использования функций. Различные функции получили немного другую семантику, поэтому ряд функций пришлось переименовать. Расширения, использующие старый API, по-прежнему будут компилироваться, но не будут участвовать в сборке мусора, поэтому их обновление для версии 2.2 следует считать довольно приоритетным.

    Чтобы обновить модуль расширения до нового API, выполните следующие шаги:

  • Переименуйте Py_TPFLAGS_GC в Py_TPFLAGS_HAVE_GC.

  • Используйте PyObject_GC_New() или PyObject_GC_NewVar() для выделения

    объектов, а PyObject_GC_Del() для их освобождения.

  • Переименуйте PyObject_GC_Init() в PyObject_GC_Track() и PyObject_GC_Fini() в PyObject_GC_UnTrack().

  • Удалите PyGC_HEAD_SIZE из расчётов размера объекта.

  • Удалите вызовы PyObject_AS_GC() и PyObject_FROM_GC().

  • Новая форматная последовательность et была добавлена в PyArg_ParseTuple(); et принимает как параметр, так и имя кодировки, и преобразует параметр в заданную кодировку, если параметр оказывается строкой Unicode, или оставляет его без изменений, если это 8-битная строка, предполагая, что она уже находится в нужной кодировке. Это отличается от символа формата es, который предполагает, что 8-битные строки находятся в кодировке ASCII по умолчанию в Python, и преобразует их в указанную новую кодировку. (Автор: М.-А. Лембург; используется для поддержки MBCS в Windows, описанной в следующем разделе.)

  • Функция разбора аргументов PyArg_UnpackTuple() – другая, она проще и, предположительно, быстрее. Вместо указания строки формата вызывающий просто задаёт минимальное и максимальное ожидаемое количество аргументов и набор указателей на переменные типа PyObject*, которые будут заполнены значениями аргументов.

  • В таблицах определений методов доступны два новых флага METH_NOARGS и METH_O, упрощающие реализацию методов без аргументов или с одним нетипизированным аргументом. Вызов таких методов эффективнее, чем вызов соответствующего метода, использующего METH_VARARGS. Кроме того, старый стиль написания методов на C METH_OLDARGS теперь официально устарел.

  • Добавлены две новые функции-обёртки PyOS_snprintf() и PyOS_vsnprintf(), предоставляющие кроссплатформенные реализации для относительно новых API библиотеки C snprintf() и vsnprintf(). В отличие от стандартных функций sprintf() и vsprintf(), версии Python проверяют границы используемого буфера для защиты от переполнения буфера. (Автор: M.-A. Lemburg.)

  • Функция _PyTuple_Resize() лишилась неиспользуемого параметра, так что теперь она принимает 2 параметра вместо 3. Третий аргумент никогда не использовался, и при переносе кода с более ранних версий на Python 2.2 его можно просто отбросить.

Другие изменения и исправленияOther Changes and Fixes

Как обычно, было множество других улучшений и исправлений ошибок, разбросанных по всему дереву исходного кода. Поиск по журналам изменений CVS показывает, что между Python 2.1 и 2.2 было применено 527 патчей и исправлено 683 ошибки; в 2.2.1 применено 139 патчей и исправлено 143 ошибки; в 2.2.2 применено 106 патчей и исправлено 82 ошибки. Эти цифры, вероятно, занижены.

Некоторые из наиболее заметных изменений:

  • Код порта Python для MacOS, поддерживаемый Джеком Янсеном, теперь хранится в главном дереве CVS Python, и было внесено много изменений для поддержки MacOS X.

    Самое значительное изменение – возможность собрать Python в виде фреймворка, включаемая указанием опции --enable-framework скрипту configure при компиляции Python. По словам Джека Янсена, «Это устанавливает самодостаточную установку Python вместе с «клеем» фреймворка OS X в /Library/Frameworks/Python.framework (или другое место по выбору). Пока что от этого мало непосредственной пользы (на самом деле есть недостаток: нужно изменить PATH, чтобы найти Python), но это основа для создания полноценного приложения Python, портирования MacPython IDE, возможного использования Python в качестве стандартного скриптового языка OSA и многого другого».

    Большинство модулей инструментария MacPython, которые взаимодействуют с API MacOS, такими как оконная система, QuickTime, скриптинг и т.д., были портированы на OS X, но оставлены закомментированными в setup.py. Желающие поэкспериментировать с этими модулями могут раскомментировать их вручную.

  • Передача именованных аргументов встроенным функциям, которые их не принимают, теперь вызывает исключение TypeError с сообщением «функция не принимает именованных аргументов».

  • Слабые ссылки, добавленные в Python 2.1 как модуль расширения, теперь являются частью ядра, поскольку они используются в реализации классов нового стиля. Исключение ReferenceError соответственно перемещено из модуля weakref и стало встроенным исключением.

  • Новый скрипт Tools/scripts/cleanfuture.py от Тима Питерса автоматически удаляет устаревшие операторы __future__ из исходного кода Python.

  • Во встроенную функцию compile() добавлен дополнительный аргумент flags, так что теперь поведение операторов __future__ можно корректно наблюдать в симулированных оболочках, например в IDLE и других средах разработки. Это описано в PEP 264. (Автор: Michael Hudson.)

  • Новая лицензия, введённая в Python 1.6, не была совместима с GPL. Это исправлено небольшими текстовыми изменениями в лицензии 2.2, так что теперь снова разрешено встраивать Python в программы под GPL. Обратите внимание, что сам Python не под GPL, а распространяется по лицензии, по существу эквивалентной лицензии BSD, как и раньше. Изменения лицензии также были применены к релизам Python 2.0.1 и 2.1.1.

  • При получении имени файла в Unicode на Windows Python теперь преобразует его в строку в кодировке MBCS, как используется API файлов Microsoft. Поскольку API файлов явно используют MBCS, выбор Python в пользу ASCII в качестве кодировки по умолчанию оказывается неудобным. На Unix используется набор символов локали, если доступен locale.nl_langinfo(CODESET). (Поддержка Windows предоставлена Марком Хаммондом при содействии Марка-Андре Лембурга. Поддержка Unix добавлена Мартином фон Лёвисом.)

  • Поддержка больших файлов теперь включена на Windows. (Автор: Tim Peters.)

  • Скрипт Tools/scripts/ftpmirror.py теперь анализирует файл .netrc, если он есть. (Автор: Mike Romberg.)

  • Некоторые возможности объекта, возвращаемого функцией xrange(), теперь устарели и вызывают предупреждения при обращении к ним; они исчезнут в Python 2.3. Объекты xrange пытались притворяться полноценными последовательностями, поддерживая срезы, умножение последовательностей и оператор in, но эти возможности редко использовались и поэтому были ошибочными. Метод tolist() и атрибуты start, stop, step также устаревают. На уровне C четвёртый аргумент функции PyRange_New(), repeat, также устарел.

  • Было множество патчей к реализации словарей, в основном для исправления потенциальных дампов ядра, если словарь содержит объекты, которые хитро изменили своё хеш-значение или изменили сам словарь, в котором содержались. Некоторое время python-dev вошёл в плавный ритм: Майкл Хадсон находил случай, приводящий к дампу ядра, Тим Питерс исправлял ошибку, Майкл находил другой случай, и так по кругу.

  • На Windows Python теперь можно скомпилировать с помощью Borland C благодаря ряду патчей, предоставленных Стивеном Хансеном, хотя результат пока не полностью функционален. (Но это есть прогресс…)

  • Ещё одно улучшение Windows: компания Wise Solutions щедро предоставила PythonLabs возможность использовать их систему InstallerMaster 8.1. Ранние инсталляторы PythonLabs для Windows использовали Wise 5.0a, который уже начинал показывать свой возраст. (Упаковано Тимом Питерсом.)

  • Файлы, оканчивающиеся на .pyw, теперь можно импортировать в Windows. .pyw – это специфичное для Windows обозначение, используемое для указания, что скрипт должен запускаться с помощью PYTHONW.EXE вместо PYTHON.EXE, чтобы не появлялась консоль DOS для вывода. Этот патч позволяет импортировать такие скрипты, если они также могут использоваться как модули. (Реализовано Дэвидом Боленом.)

  • На платформах, где Python использует функцию C dlopen() для загрузки модулей расширения, теперь можно задавать флаги, используемые dlopen(), с помощью функций sys.getdlopenflags() и sys.setdlopenflags(). (Автор: Bram Stolk.)

  • Встроенная функция pow() больше не поддерживает 3 аргумента, когда передаются числа с плавающей запятой. pow(x, y, z) возвращает (x**y) % z, но это никогда не бывает полезным для чисел с плавающей запятой, и конечный результат непредсказуемо варьируется в зависимости от платформы. Вызов вида pow(2.0, 8.0, 7.0) теперь вызовет исключение TypeError.

БлагодарностиAcknowledgements

Автор хотел бы поблагодарить следующих людей за предложения, исправления и помощь с различными черновиками этой статьи: Фред Бреммер, Кейт Бриггс, Эндрю Далк, Фред Л. Дрейк-младший, Карел Феллингер, Дэвид Гуджер, Марк Хаммонд, Стивен Хансен, Майкл Хадсон, Джек Янсен, Марк-Андре Лембург, Мартин фон Лёвис, Фредрик Лунд, Майкл МакЛей, Ник Мэтьюсон, Пол Мур, Густаво Нимейер, Дон О’Доннелл, Юнас Пааласма, Тим Питерс, Йенс Кваде, Том Рейнхардт, Нил Шеменауэр, Гвидо ван Россум, Грег Уорд, Эдвард Уэлборн.