Що нового в Python 2.2

Автор

A.M. Kuchling

вступ

У цій статті пояснюється нові функції в 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: Зміни типу та класу

Найбільші та наймасштабніші зміни в Python 2.2 стосуються моделі об’єктів і класів Python. Зміни мають бути зворотно сумісними, тому ймовірно, що ваш код працюватиме без змін, але зміни надають деякі дивовижні нові можливості. Перш ніж почати цей, найдовший і найскладніший розділ цієї статті, я наведу огляд змін і запропоную деякі коментарі.

A long time ago I wrote a Web page listing flaws in Python’s design. One of the most significant flaws was that it’s impossible to subclass Python types implemented in C. In particular, it’s not possible to subclass built-in types, so you can’t just subclass, say, lists in order to add a single useful method to them. The UserList module provides a class that supports all of the methods of lists and that can be subclassed further, but there’s lots of C code that expects a regular Python list and won’t accept a UserList instance.

У Python 2.2 це виправлено, і в процесі додано кілька захоплюючих нових можливостей. Короткий зміст:

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

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

  • Також можна автоматично викликати методи під час доступу або встановлення атрибута екземпляра за допомогою нового механізму під назвою properties. Багато варіантів використання __getattr__() можна переписати, щоб замість нього використовувати властивості, що робить кінцевий код простішим і швидшим. В якості невеликої додаткової переваги атрибути тепер також можуть мати рядки документації.

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

Деякі користувачі висловили стурбованість усіма цими змінами. Звісно, вони кажуть, що нові функції гарні та піддаються різноманітним хитрощам, які були недоступні в попередніх версіях Python, але вони також ускладнюють мову. Деякі люди кажуть, що вони завжди рекомендували Python за його простоту, і вважають, що його простота втрачається.

Особисто я вважаю, що хвилюватися не варто. Багато нових функцій досить езотеричні, і ви можете написати багато коду Python, навіть не знаючи про них. Написати простий курс не складніше, ніж будь-коли, тому вам не потрібно турбуватися про їх вивчення чи викладання, якщо вони дійсно не потрібні. Деякі дуже складні завдання, які раніше були можливими лише на C, тепер будуть можливими на чистому Python, і, на мій погляд, це все на краще.

Я не збираюся намагатися охопити кожен кутовий випадок і невеликі зміни, які були необхідні для того, щоб нові функції працювали. Натомість у цьому розділі буде намальовано лише широкі штрихи. Перегляньте розділ Пов’язані посилання, «Пов’язані посилання», щоб отримати додаткові джерела інформації про нову об’єктну модель Python 2.2.

Старі та нові класи

По-перше, ви повинні знати, що 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.

Дескриптори

У попередніх версіях Python не було узгодженого способу дізнатися, які атрибути та методи підтримувалися об’єктом. Були деякі неофіційні домовленості, такі як визначення __members__ і __methods__ атрибутів, які були списками імен, але часто автор типу розширення або класу не турбувався про їх визначення. Ви можете повернутися до перевірки __dict__ об’єкта, але коли використовується успадкування класу або довільний хук __getattr__(), це може бути неточним.

Одна велика ідея, яка лежить в основі нової моделі класу, полягає в тому, що API для опису атрибутів об’єкта за допомогою descriptors було формалізовано. Дескриптори вказують значення атрибута, вказуючи, чи це метод, чи поле. З API дескриптора статичні методи та методи класу стають можливими, а також більш екзотичні конструкції.

Дескриптори атрибутів — це об’єкти, які знаходяться всередині об’єктів класу та мають кілька власних атрибутів:

  • __name__ це ім’я атрибута.

  • __doc__ — рядок документації атрибута.

  • __get__(object) — це метод, який отримує значення атрибута з object.

  • __set__(object, value) встановлює атрибут object на value.

  • __delete__(object, value) видаляє атрибут value object.

Наприклад, коли ви пишете 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.

Більше нових функцій, таких як слоти та властивості, також реалізовано як нові типи дескрипторів, і не важко написати клас дескриптора, який робить щось нове. Наприклад, можна було б написати клас дескрипторів, який би дозволив написати передумови та постумови методу в стилі Ейфеля. Клас, який використовує цю функцію, можна визначити так:

from eiffel import eiffelmethod

class C(object):
    def f(self, arg1, arg2):
        # The actual function
        ...
    def pre_f(self):
        # Check preconditions
        ...
    def post_f(self):
        # Check postconditions
        ...

    f = eiffelmethod(f, pre_f, post_f)

Зауважте, що особа, яка використовує новий eiffelmethod(), не повинна нічого розуміти про дескриптори. Ось чому я думаю, що нові функції не збільшують основну складність мови. Буде кілька майстрів, які повинні знати про це, щоб написати eiffelmethod() або ZODB або щось інше, але більшість користувачів просто напишуть код поверх отриманих бібліотек і проігнорують деталі реалізації.

Множинне успадкування: ромбовидне правило

Множинне успадкування також стало більш корисним завдяки зміні правил, за якими розпізнаються імена. Розглянемо цей набір класів (діаграма взята з 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), яка повертає пов’язаний об’єкт суперкласу (а не фактичний об’єкт класу). Ця форма буде використовуватися в методах для виклику методу в суперкласі; наприклад, метод D save() виглядатиме так:

class D (B,C):
    def save (self):
        # Call superclass .save()
        super(D, self).save()
        # Save D's private information here
        ...

super() також може повертати незв’язані об’єкти суперкласу під час виклику super(class) або super(class1, class2), але це, мабуть, не часто буде корисним.

Доступ до атрибутів

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

По-перше, __getattr__(attr_name) все ще підтримується класами нового стилю, і нічого в ньому не змінилося. Як і раніше, він буде викликаний, коли буде зроблена спроба отримати доступ до obj.foo, а атрибут з назвою foo не знайдено в словнику примірника.

Класи нового стилю також підтримують новий метод, __getattribute__(attr_name). Різниця між цими двома методами полягає в тому, що __getattribute__() завжди викликається щоразу, коли здійснюється доступ до будь-якого атрибута, тоді як старий __getattr__() викликається, лише якщо foo не знайдено в екземплярі словник.

Однак підтримка Python 2.2 properties часто буде простішим способом перехоплення посилань на атрибути. Написання методу __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 ...

    # Define a property.  The 'delete this attribute'
    # method is defined as None, so the attribute
    # can't be deleted.
    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'

Зверніть увагу, як ви отримуєте AttributeError під час спроби призначити атрибут, не вказаний у __slots__.

PEP 234: Ітератори

Іншим значним доповненням до 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
>>>

У 2.2 оператор Python for більше не очікує послідовності; він очікує щось, для чого iter() поверне ітератор. Для зворотної сумісності та зручності ітератор автоматично створюється для послідовностей, які не реалізують __iter__() або слот tp_iter, тому for i в [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:
    # do something for each line
    ...

Зауважте, що в ітераторі можна рухатися лише вперед; немає способу отримати попередній елемент, скинути ітератор або зробити його копію. Об’єкт-ітератор може надати такі додаткові можливості, але протокол ітератора потребує лише методу next().

Дивись також

PEP 234 - Ітератори

Написаний Ка-Пінг Йі та GvR; реалізований командою Python Labs, переважно GvR і Тімом Пітерсом.

PEP 255: Прості генератори

Генератори — ще одна нова функція, яка взаємодіє з появою ітераторів.

Ви, безсумнівно, знайомі з тим, як працюють виклики функцій у 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 містить ще кілька цікавих прикладів. Найпростіший реалізує рекурсивний обхід дерева за допомогою генераторів.

# A recursive generator that generates Tree leaves in 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-Queens (розміщення $N$ ферзів на $NxN$ шахівниці так, щоб жодна королева не загрожувала іншій) і Knight’s Tour (a маршрут, який веде лицаря до кожного поля $NxN$ шахівниці, не відвідуючи жодного поля двічі).

Ідея генераторів походить від інших мов програмування, особливо Icon (https://www.cs.arizona.edu/icon/), де ідея генераторів є центральною. У Icon кожен вираз і виклик функції поводяться як генератор. Один приклад із «Огляду мови програмування значків» на https://www.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 - Прості генератори

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

PEP 237: Об’єднання довгих і цілих чисел

В останніх версіях різниця між звичайними цілими числами, які є 32-розрядними значеннями на більшості машин, і довгими цілими числами, які можуть мати довільний розмір, стала неприємною. Наприклад, на платформах, які підтримують файли розміром понад 2**32 байти, метод tell() файлових об’єктів має повертати довге ціле число. Однак існували різні частини Python, які очікували простих цілих чисел і викликали помилку, якщо натомість було надано довге ціле число. Наприклад, у Python 1.5 лише звичайні цілі числа можна було використовувати як індекс фрагмента, а 'abc'[1L:] викликав би виняток TypeError із повідомленням «індекс фрагмента повинен бути 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: Зміна оператора поділу

Найбільш суперечлива зміна в 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 і так далі. «Поділ на поверх» - це те, що наразі робить оператор / 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 - Зміна оператора ділення

Автори Моше Цадка та Гвідо ван Россум. Реалізовано Гвідо ван Россумом..

Зміни Unicode

Підтримку Python Unicode було дещо вдосконалено у версії 2.2. Рядки Unicode зазвичай зберігаються як UCS-2, як 16-розрядні цілі числа без знаку. Python 2.2 також можна скомпілювати для використання UCS-4, 32-розрядних цілих чисел без знаку, як внутрішнього кодування, надаючи --enable-unicode=ucs4 до сценарію конфігурації. (Також можна вказати --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. Симетричний метод decode([*encoding*]) було додано до 8-бітових рядків (хоча не до рядків Unicode) у 2.2. decode() припускає, що рядок знаходиться у вказаному кодуванні, і декодує його, повертаючи те, що повертає кодек.

За допомогою цієї нової функції було додано кодеки для завдань, які безпосередньо не пов’язані з Unicode. Наприклад, додано кодеки для uu-кодування, кодування MIME base64 і стиснення за допомогою модуля 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

Написав Пол Прескод.

PEP 227: Вкладені області

У Python 2.1 статичні вкладені області було додано як необов’язкову функцію, яку можна ввімкнути за допомогою директиви from __future__ import nested_scopes. У версії 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():
    # The next line is a syntax error
    exec 'x=2'
    def g():
        return x

Рядок 4, що містить інструкцію exec, є синтаксичною помилкою, оскільки exec визначатиме нову локальну змінну з назвою x, до значення якої має отримати доступ g().

Це не повинно бути великим обмеженням, оскільки exec рідко використовується в більшості коду Python (і коли він використовується, це часто свідчить про поганий дизайн).

Дивись також

PEP 227 - Статично вкладені області

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

Нові та вдосконалені модулі

  • Модуль xmlrpclib був доданий до стандартної бібліотеки Фредріком Лундом, надаючи підтримку для написання клієнтів XML-RPC. XML-RPC — це простий протокол віддаленого виклику процедури, створений на основі HTTP і XML. Наприклад, наведений нижче фрагмент отримує список каналів RSS із мережі O’Reilly, а потім перераховує останні заголовки для одного каналу:

    import xmlrpclib
    s = xmlrpclib.Server(
          'http://www.oreillynet.com/meerkat/xml-rpc/server.php')
    channels = s.meerkat.getChannels()
    # channels is a list of dictionaries, like this:
    # [{'id': 4, 'title': 'Freshmeat Daily News'}
    #  {'id': 190, 'title': '32Bits Online'},
    #  {'id': 4549, 'title': '3DGamers'}, ... ]
    
    # Get the items for one channel
    items = s.meerkat.getItems( {'channel': 4} )
    
    # 'items' is another list of dictionaries, like this:
    # [{'link': 'http://freshmeat.net/releases/52719/',
    #   'description': 'A utility which converts HTML to XSL FO.',
    #   'title': 'html2fo 0.3 (Default)'}, ... ]
    

    Модуль SimpleXMLRPCServer дозволяє легко створювати прості сервери XML-RPC. Перегляньте http://xmlrpc.scripting.com/ для отримання додаткової інформації про XML-RPC.

  • Новий модуль hmac реалізує алгоритм HMAC, описаний RFC 2104. (Надав Герхард Херінг.)

  • Кілька функцій, які спочатку повертали довгі кортежі, тепер повертають псевдопослідовності, які все ще поводяться як кортежі, але також мають мнемонічні атрибути, такі як 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(назва_файлу).st_size.

    Оригінальний патч для цієї функції надав Нік Метьюсон.

  • Профайлер Python було значно перероблено та виправлено різні помилки в його виводі. (Надано Фредом Л. Дрейком молодшим і Тімом Пітерсом.)

  • Модуль socket можна скомпільувати для підтримки IPv6; вкажіть параметр --enable-ipv6 для сценарію налаштування Python. (Надав Дзюн-ічіро «ітоджун» Хагіно.)

  • Two new format characters were added to the struct module for 64-bit integers on platforms that support the C long long type. q is for a signed 64-bit integer, and Q is for an unsigned one. The value is returned in Python’s long integer type. (Contributed by Tim Peters.)

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

  • У механізмі SRE, що лежить в основі модуля re, було зроблено різні виправлення помилок і покращено продуктивність. Наприклад, функції re.sub() і re.split() було переписано мовою C. Інший патч пришвидшує певні діапазони символів Юнікоду в два рази, а також новий метод finditer(), який повертає ітератор для всіх неперекриваючих збігів у заданому рядку. (SRE підтримує Фредрік Лунд. Патч BIGCHARSET надав Мартін фон Льовіс.)

  • Модуль smtplib тепер підтримує RFC 2487, «Безпечний SMTP через TLS», тому тепер можна шифрувати SMTP-трафік між програмою Python і агентом транспортування пошти, якому передається повідомлення. smtplib також підтримує аутентифікацію SMTP. (Надав Герхард Херінг.)

  • Модуль imaplib, який підтримує Пірс Лаудер, підтримує кілька нових розширень: розширення NAMESPACE, визначене в RFC 2342, SORT, GETACL і SETACL. (Надано Ентоні Бакстером і Мішелем Пеллетьє.)

  • Аналіз адрес електронної пошти модулем rfc822 тепер сумісний з RFC 2822, оновленням до RFC 822. (Ім’я модуля не буде змінено на rfc2822.) Новий пакет, email, також було додано для аналізу та генерування повідомлень електронної пошти. (Надано Баррі Варшау, що є результатом його роботи над Mailman.)

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

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

  • Модуль mimetypes тепер полегшує використання альтернативних баз даних типу MIME завдяки доданню класу MimeTypes, який приймає список імен файлів для аналізу. (Надав Фред Л. Дрейк-молодший)

  • До модуля threading було додано клас Timer, який дозволяє планувати виконання активності в майбутньому. (Надав Ітамар Штул-Траурінг.)

Зміни та виправлення перекладача

Деякі зміни стосуються лише тих, хто має справу з інтерпретатором 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() на PyTPFLAGS_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 приймає як параметр, так і ім’я кодування та перетворює параметр у вказане кодування, якщо параметр виявляється рядком Юнікоду, або залишає його в спокої, якщо це 8-бітовий рядок, припускаючи, що він уже є у потрібному кодуванні. Це відрізняється від символу формату es, який припускає, що 8-бітні рядки мають типове кодування ASCII Python, і перетворює їх у вказане нове кодування. (Надано M.-A. Lemburg і використовується для підтримки MBCS у Windows, описаної в наступному розділі.)

  • A different argument parsing function, PyArg_UnpackTuple(), has been added that’s simpler and presumably faster. Instead of specifying a format string, the caller simply gives the minimum and maximum number of arguments expected, and a set of pointers to PyObject* variables that will be filled in with argument values.

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

  • Дві нові функції оболонки, PyOS_snprintf() і PyOS_vsnprintf(), були додані, щоб забезпечити кросплатформену реалізацію відносно нових snprintf() і vsnprintf() API C lib. На відміну від стандартних функцій sprintf() і vsprintf(), версії Python перевіряють межі буфера, який використовується для захисту від переповнення буфера. (Уклав М.-А. Лембург.)

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

Інші зміни та виправлення

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

Деякі з найбільш помітних змін:

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

    Найсуттєвішою зміною є можливість створювати Python як фреймворк, увімкнений шляхом надання опції --enable-framework до сценарію конфігурації під час компіляції Python. За словами Джека Янсена, «це встановлює самодостатню інсталяцію Python, а також фреймворк OS X «клей» у /Library/Frameworks/Python.framework (або в інше розташування). це додаткова перевага (насправді, є недолік, що вам потрібно змінити свій ШЛЯХ, щоб мати змогу знайти 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.

  • Додатковий аргумент flags було додано до вбудованої функції compile(), тому поведінку операторів __future__ тепер можна правильно спостерігати в змодельованих оболонках, таких як представлені IDLE та інші розробки середовищ. Це описано в PEP 264. (Надав Майкл Хадсон.)

  • Нова ліцензія, представлена разом із Python 1.6, не була сумісною з GPL. Це виправлено деякими незначними текстовими змінами в ліцензії 2.2, тому тепер можна знову вставляти Python у програму GPL. Зауважте, що сам Python не підпадає під ліцензію GPL, а натомість діє під ліцензією, яка, по суті, еквівалентна ліцензії BSD, як і було завжди. Зміни ліцензії також було застосовано до випусків Python 2.0.1 і 2.1.1.

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

  • Підтримка великих файлів тепер увімкнена в Windows. (Надав Тім Пітерс.)

  • Сценарій Tools/scripts/ftpmirror.py тепер аналізує файл .netrc, якщо він у вас є. (Надав Майк Ромберг.)

  • Деякі функції об’єкта, що повертаються функцією 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() функції. (Надано Бремом Столком.)

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

Подяки

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