Що нового в Python 2.3

Автор

A.M. Kuchling

У цій статті пояснюються нові функції Python 2.3. Python 2.3 був випущений 29 липня 2003 року.

Основними темами для Python 2.3 є вдосконалення деяких функцій, доданих у 2.2, додавання різних невеликих, але корисних покращень до основної мови та розширення стандартної бібліотеки. Нова об’єктна модель, представлена в попередній версії, отримала переваги від 18 місяців виправлення помилок і зусиль з оптимізації, які покращили продуктивність класів нового стилю. Було додано кілька нових вбудованих функцій, таких як sum() і enumerate(). Оператор in тепер можна використовувати для пошуку підрядка (наприклад, "ab" у "abc" повертає True).

Деякі з багатьох нових функцій бібліотеки включають типи даних Boolean, set, heap і date/time, можливість імпортувати модулі з архівів у форматі ZIP, підтримку метаданих для довгоочікуваного каталогу Python, оновлену версію IDLE та модулі. для реєстрації повідомлень, обтікання текстом, аналізу файлів CSV, обробки параметрів командного рядка, використання баз даних BerkeleyDB… список нових і вдосконалених модулів довгий.

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

PEP 218: Тип даних стандартного набору

Новий модуль sets містить реалізацію типу даних set. Клас Set призначений для змінних наборів, наборів, члени яких можна додавати та видаляти. Клас ImmutableSet призначений для наборів, які не можна змінювати, тому екземпляри ImmutableSet можна використовувати як ключі словника. Набори створюються на основі словників, тому елементи в наборі мають бути хешованими.

Ось простий приклад:

>>> import sets
>>> S = sets.Set([1,2,3])
>>> S
Set([1, 2, 3])
>>> 1 in S
True
>>> 0 in S
False
>>> S.add(5)
>>> S.remove(3)
>>> S
Set([1, 2, 5])
>>>

Об’єднання та перетин множин можна обчислити за допомогою методів union() і intersection(); в альтернативній нотації використовуються порозрядні оператори & і |. Змінні набори також мають на місці версії цих методів, union_update() і intersection_update().

>>> S1 = sets.Set([1,2,3])
>>> S2 = sets.Set([4,5,6])
>>> S1.union(S2)
Set([1, 2, 3, 4, 5, 6])
>>> S1 | S2                  # Alternative notation
Set([1, 2, 3, 4, 5, 6])
>>> S1.intersection(S2)
Set([])
>>> S1 & S2                  # Alternative notation
Set([])
>>> S1.union_update(S2)
>>> S1
Set([1, 2, 3, 4, 5, 6])
>>>

Також можна взяти симетричну різницю двох наборів. Це набір усіх елементів об’єднання, які не перебувають у перетині. Іншим способом виразити це є те, що симетрична різниця містить усі елементи, які знаходяться в одній множині. Знову ж таки, є альтернативне позначення (^) і версія на місці з незграбною назвою symmetric_difference_update().

>>> S1 = sets.Set([1,2,3,4])
>>> S2 = sets.Set([3,4,5,6])
>>> S1.symmetric_difference(S2)
Set([1, 2, 5, 6])
>>> S1 ^ S2
Set([1, 2, 5, 6])
>>>

Існують також методи issubset() і issuperset() для перевірки того, чи є один набір підмножиною або надмножиною іншого:

>>> S1 = sets.Set([1,2,3])
>>> S2 = sets.Set([2,3])
>>> S2.issubset(S1)
True
>>> S1.issubset(S2)
False
>>> S1.issuperset(S2)
True
>>>

Дивись також

PEP 218 - Додавання вбудованого типу об’єкта Set

PEP, написаний Грегом В. Вілсоном. Реалізовано Грегом В. Вілсоном, Алексом Мартеллі та GvR.

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

У Python 2.2 генератори були додані як необов’язкова функція, яка вмикається директивою from __future__ import generators. У версії 2.3 генератори більше не потребують спеціального вмикання, і тепер вони завжди присутні; це означає, що yield тепер завжди є ключовим словом. Решта цього розділу є копією опису генераторів із документа «Що нового в Python 2.2»; якщо ви читали це ще під час виходу Python 2.2, ви можете пропустити решту цього розділу.

Ви, безсумнівно, знайомі з тим, як працюють виклики функцій у Python або C. Коли ви викликаєте функцію, вона отримує приватний простір імен, де створюються її локальні змінні. Коли функція досягає оператора return, локальні змінні знищуються, а отримане значення повертається до викликаючого. Пізніший виклик тієї ж функції отримає новий набір локальних змінних. Але що, якби локальні змінні не були викинуті під час виходу з функції? Що, якби ви могли пізніше відновити функцію, де вона була зупинена? Це те, що забезпечують генератори; їх можна розглядати як відновлювані функції.

Ось найпростіший приклад функції генератора:

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

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

Коли ви викликаєте функцію генератора, вона не повертає жодного значення; замість цього він повертає об’єкт генератора, який підтримує протокол ітератора. Під час виконання оператора 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 263: Кодування вихідного коду

Вихідні файли Python тепер можна оголошувати такими, що мають різні кодування набору символів. Кодування оголошується шляхом додавання спеціально відформатованого коментаря в перший або другий рядок вихідного файлу. Наприклад, файл UTF-8 можна оголосити за допомогою:

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

Без такої декларації кодування за замовчуванням використовується 7-бітне кодування ASCII. Виконання або імпортування модулів, які містять рядкові літерали з 8-бітовими символами та не мають декларації кодування, призведе до того, що Python 2.3 повідомить DeprecationWarning; у 2.4 це буде синтаксична помилка.

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

Дивись також

PEP 263 - Визначення кодувань вихідного коду Python

Автори: Марк-Андре Лембург і Мартін фон Льовіс; реалізовано Сузукі Хісао та Мартіном фон Льовісом.

PEP 273: Імпортування модулів із ZIP-архівів

Новий модуль zipimport додає підтримку для імпорту модулів з архіву ZIP-формату. Вам не потрібно явно імпортувати модуль; його буде автоматично імпортовано, якщо назву файлу ZIP-архіву буде додано до sys.path. Наприклад:

amk@nyman:~/src/python$ unzip -l /tmp/example.zip
Archive:  /tmp/example.zip
  Length     Date   Time    Name
 --------    ----   ----    ----
     8467  11-26-02 22:30   jwzthreading.py
 --------                   -------
     8467                   1 file
amk@nyman:~/src/python$ ./python
Python 2.3 (#1, Aug 1 2003, 19:54:32)
>>> import sys
>>> sys.path.insert(0, '/tmp/example.zip')  # Add .zip file to front of path
>>> import jwzthreading
>>> jwzthreading.__file__
'/tmp/example.zip/jwzthreading.py'
>>>

Запис у sys.path тепер може бути назвою файлу ZIP-архіву. ZIP-архів може містити будь-які файли, але можна імпортувати лише файли з назвами *.py, *.pyc або *.pyo. Якщо архів містить лише файли *.py, Python не намагатиметься змінити архів, додавши відповідний файл *.pyc, тобто якщо архів ZIP не містить *.pyc, імпортування може бути досить повільним.

Шлях всередині архіву також можна вказати лише для імпорту з підкаталогу; наприклад, шлях /tmp/example.zip/lib/ імпортуватиметься лише з підкаталогу lib/ в архіві.

Дивись також

PEP 273 - імпортувати модулі з Zip-архівів

Написав Джеймс К. Алстром, який також забезпечив реалізацію. Python 2.3 відповідає специфікації в PEP 273, але використовує реалізацію, написану Джастом ван Россумом, яка використовує хуки імпорту, описані в PEP 302. Перегляньте розділ PEP 302: нові імпортні гачки для опису нових хуків імпорту.

PEP 277: Підтримка імен файлів Unicode для Windows NT

У Windows NT, 2000 і XP система зберігає імена файлів як рядки Unicode. Традиційно Python представляє імена файлів у вигляді байтових рядків, що є неадекватним, оскільки робить деякі імена файлів недоступними.

Python тепер дозволяє використовувати довільні рядки Unicode (в межах обмежень файлової системи) для всіх функцій, які очікують імен файлів, особливо для вбудованої функції open(). Якщо рядок Unicode передається до os.listdir(), Python тепер повертає список рядків Unicode. Нова функція, os.getcwdu(), повертає поточний каталог як рядок Unicode.

Байтові рядки все ще працюють як імена файлів, і в Windows Python прозоро перетворює їх у Unicode за допомогою кодування mbcs.

Інші системи також дозволяють рядки Unicode як імена файлів, але перетворюють їх на рядки байтів перед передачею в систему, що може спричинити виникнення UnicodeError. Програми можуть перевірити, чи підтримуються довільні рядки Unicode як імена файлів, перевіривши os.path.supports_unicode_filenames, логічне значення.

У MacOS os.listdir() тепер може повертати імена файлів у кодуванні Unicode.

Дивись також

PEP 277 - Підтримка імен файлів Unicode для Windows NT

Автор Ніл Ходжсон; реалізований Нілом Ходжсоном, Мартіном фон Льовісом і Марком Хаммондом.

PEP 278: універсальна підтримка нового рядка

Сьогодні використовуються три основні операційні системи: Microsoft Windows, Macintosh OS від Apple і різні похідні Unix. Невелике роздратування кросплатформної роботи полягає в тому, що всі ці три платформи використовують різні символи для позначення кінців рядків у текстових файлах. Unix використовує символ переводу рядка (символ ASCII 10), MacOS використовує символ повернення каретки (символ ASCII 13), а Windows використовує двосимвольну послідовність повернення каретки плюс новий рядок.

Файлові об’єкти Python тепер можуть підтримувати угоди про кінець рядка, відмінні від того, за яким іде платформа, на якій працює Python. Відкриття файлу в режимі 'U' або 'rU' відкриє файл для читання в режимі universal newlines. Усі три правила закінчення рядків буде перекладено на '\n' у рядках, які повертаються різними файловими методами, такими як read() і readline().

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

Цю функцію можна вимкнути під час компіляції Python, вказавши параметр --without-universal-newlines під час виконання сценарію configure Python.

Дивись також

PEP 278 - Універсальна підтримка нового рядка

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

PEP 279: enumerate()

Нова вбудована функція, enumerate(), зробить певні цикли трохи зрозумілішими. enumerate(thing), де thing є ітератором або послідовністю, повертає ітератор, який поверне (0, thing[0]), (1, thing[1]), (2, thing[2]) і так далі.

Загальна ідіома зміни кожного елемента списку виглядає так:

for i in range(len(L)):
    item = L[i]
    # ... compute some result based on item ...
    L[i] = result

Це можна переписати за допомогою enumerate() як:

for i, item in enumerate(L):
    # ... compute some result based on item ...
    L[i] = result

Дивись також

PEP 279 - Вбудована функція enumerate().

Написаний і реалізований Реймондом Д. Хеттінгером.

PEP 282: пакет журналів

Стандартний пакет для запису журналів, logging, було додано до Python 2.3. Він забезпечує потужний і гнучкий механізм для генерації результатів журналювання, які потім можна фільтрувати та обробляти різними способами. Файл конфігурації, написаний у стандартному форматі, можна використовувати для керування поведінкою програми в журналі. Python включає обробники, які записуватимуть записи журналу до стандартної помилки або до файлу чи сокета, надсилатимуть їх до системного журналу чи навіть електронною поштою на певну адресу; звичайно, також можна написати власні класи обробників.

Клас Logger є основним класом. Більшість програмного коду працюватиме з одним або кількома об’єктами Logger, кожен з яких використовується окремою підсистемою програми. Кожен Logger ідентифікується за назвою, і імена організовані в ієрархію за допомогою . як розділювача компонентів. Наприклад, у вас можуть бути екземпляри Logger з іменами server, server.auth і server.network. Останні два екземпляри знаходяться нижче сервера в ієрархії. Це означає, що якщо ви підвищите детальність для server або спрямуєте server повідомлення до іншого обробника, зміни також застосовуватимуться до записів, зареєстрованих у server.auth і server.network. Існує також корінь Logger, який є батьківським для всіх інших реєстраторів.

Для простого використання пакет logging містить деякі зручні функції, які завжди використовують кореневий журнал:

import logging

logging.debug('Debugging information')
logging.info('Informational message')
logging.warning('Warning:config file %s not found', 'server.conf')
logging.error('Error occurred')
logging.critical('Critical error -- shutting down')

Це дає такий вихід:

WARNING:root:Warning:config file server.conf not found
ERROR:root:Error occurred
CRITICAL:root:Critical error -- shutting down

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

Зверніть увагу на використання виклику warning() операторів форматування рядків; усі функції для реєстрації повідомлень приймають аргументи (msg, arg1, arg2, ...) і записують рядок, що є результатом msg % (arg1, arg2, ...).

Існує також функція exception(), яка записує останню трасування. Будь-яка інша функція також записуватиме зворотне відстеження, якщо ви вкажете справжнє значення для ключового аргументу exc_info.

def f():
    try:    1/0
    except: logging.exception('Problem recorded')

f()

Це дає такий вихід:

ERROR:root:Problem recorded
Traceback (most recent call last):
  File "t.py", line 6, in f
    1/0
ZeroDivisionError: integer division or modulo by zero

Трохи просунутіші програми використовуватимуть інший реєстратор, ніж кореневий реєстратор. Функція getLogger(name) використовується для отримання певного журналу, створення його, якщо він ще не існує. getLogger(None) повертає кореневий реєстратор.

log = logging.getLogger('server')
 ...
log.info('Listening on port %i', port)
 ...
log.critical('Disk full')
 ...

Записи журналу зазвичай поширюються вгору по ієрархії, тому повідомлення, зареєстроване на server.auth, також бачать server і root, але Logger може запобігти цьому, встановивши його атрибут propagate до False.

There are more classes provided by the logging package that can be customized. When a Logger instance is told to log a message, it creates a LogRecord instance that is sent to any number of different Handler instances. Loggers and handlers can also have an attached list of filters, and each filter can cause the LogRecord to be ignored or can modify the record before passing it along. When they’re finally output, LogRecord instances are converted to text by a Formatter class. All of these classes can be replaced by your own specially-written classes.

З усіма цими функціями пакет logging має забезпечити достатню гнучкість навіть для найскладніших програм. Це лише неповний огляд його функцій, тому, будь ласка, перегляньте довідкову документацію пакета, щоб отримати всі деталі. Читання PEP 282 також буде корисним.

Дивись також

PEP 282 - Система реєстрації

Автори: Віней Саджип і Трент Мік; реалізовано Вінаєм Саджипом.

PEP 285: логічний тип

Логічний тип було додано до Python 2.3. Дві нові константи додано до модуля __builtin__, True і False. (True і False константи були додані до вбудованих компонентів у Python 2.2.1, але версії 2.2.1 просто встановлені на цілі значення 1 і 0 і не відрізняються типу.)

Об’єкт типу для цього нового типу називається bool; конструктор для нього приймає будь-яке значення Python і перетворює його на True або False.

>>> bool(1)
True
>>> bool(0)
False
>>> bool([])
False
>>> bool( (1,) )
True

Більшість стандартних бібліотечних модулів і вбудованих функцій було змінено для повернення логічних значень.

>>> obj = []
>>> hasattr(obj, 'append')
True
>>> isinstance(obj, list)
True
>>> isinstance(obj, tuple)
False

Логічні значення Python були додані з головною метою зробити код зрозумілішим. Наприклад, якщо ви читаєте функцію та зустрічаєте оператор повернути 1, ви можете запитати, чи 1 представляє логічне значення істинності, індекс або коефіцієнт, який множить якусь іншу величину. Однак, якщо оператор повернути Істину, значення значення, що повертається, цілком зрозуміле.

Логічні значення Python не додано задля суворої перевірки типу. Дуже сувора мова, така як Паскаль, також завадить вам виконувати арифметику з булевими значеннями, і вимагатиме, щоб вираз у операторі if завжди обчислювався як логічний результат. Python не є таким суворим і ніколи не буде, про що прямо говорить PEP 285. Це означає, що ви все ще можете використовувати будь-який вираз у операторі if, навіть той, який обчислюється як список, кортеж або якийсь випадковий об’єкт. Логічний тип є підкласом класу int, тому арифметика з використанням логічного значення все ще працює.

>>> True + 1
2
>>> False + 1
1
>>> False * 75
0
>>> True * 75
75

Підводячи підсумок True і False у реченні: це альтернативні способи написання цілих значень 1 і 0, з тією єдиною різницею, що str() і repr() повертає рядки 'True' і 'False' замість '1' і '0'.

Дивись також

PEP 285 - Додавання типу bool

Написано та реалізовано GvR.

PEP 293: Зворотні виклики обробки помилок кодека

Під час кодування рядка Юнікод у рядок байтів можуть зустрітися некодовані символи. Наразі Python дозволяв вказувати обробку помилок як «строгу» (викликаючи UnicodeError), «ігнорувати» (пропускаючи символ) або «замінювати» (використовуючи знак питання у вихідному рядку), з «суворий» є поведінкою за замовчуванням. Може бути бажано вказати альтернативну обробку таких помилок, таку як вставка посилання на символ XML або посилання на сутність HTML у перетворений рядок.

Python тепер має гнучку структуру для додавання різних стратегій обробки. Нові обробники помилок можна додати за допомогою codecs.register_error(), а потім кодеки зможуть отримати доступ до обробника помилок за допомогою codecs.lookup_error(). Для кодеків, написаних мовою C, додано еквівалентний C API. Обробник помилок отримує необхідну інформацію про стан, таку як рядок, який перетворюється, позиція в рядку, де було виявлено помилку, і цільове кодування. Тоді обробник може викликати виняток або повернути рядок заміни.

За допомогою цього фреймворку було реалізовано два додаткові обробники помилок: «backslashreplace» використовує лапки Python для представлення некодованих символів, а «xmlcharrefreplace» видає посилання на символи XML.

Дивись також

PEP 293 - Помилка кодека при обробці зворотних викликів

Написав і реалізував Вальтер Дьорвальд.

PEP 301: Індекс пакетів і метадані для Distutils

Підтримка давно запитуваного каталогу Python вперше з’являється у 2.3.

Серцем каталогу є нова команда Distutils register. Запуск python setup.py register збирає метадані, що описують пакунок, наприклад його назву, версію, супроводжуючого, опис тощо, і надсилає їх на центральний сервер каталогу. Отриманий каталог доступний за адресою https://pypi.org.

Щоб зробити каталог трохи кориснішим, до функції Distutils setup() додано новий необов’язковий аргумент ключового слова classifiers. Можна надати список рядків у стилі Trove, щоб допомогти класифікувати програмне забезпечення.

Ось приклад setup.py з класифікаторами, написаними для сумісності зі старішими версіями Distutils:

from distutils import core
kw = {'name': "Quixote",
      'version': "0.5.1",
      'description': "A highly Pythonic Web application framework",
      # ...
      }

if (hasattr(core, 'setup_keywords') and
    'classifiers' in core.setup_keywords):
    kw['classifiers'] = \
        ['Topic :: Internet :: WWW/HTTP :: Dynamic Content',
         'Environment :: No Input/Output (Daemon)',
         'Intended Audience :: Developers'],

core.setup(**kw)

Повний список класифікаторів можна отримати, запустивши python setup.py register --list-classifiers.

Дивись також

PEP 301 - Індекс пакета та метадані для Distutils

Написаний і реалізований Річардом Джонсом.

PEP 302: нові імпортні гачки

Хоча з моменту появи модуля ihooks у Python 1.3 стало можливим писати користувацькі хуки імпорту, ніхто ніколи не був цим дуже задоволений, тому що писати нові хуки імпорту складно та безладно. Існували різні запропоновані альтернативи, такі як модулі imputil і iu, але жоден з них ніколи не отримав великого визнання, і жоден з них не був легким для використання з коду C.

PEP 302 запозичив ідеї у своїх попередників, особливо у модуля iu Гордона МакМіллана. До модуля sys додано три нові елементи:

  • sys.path_hooks - це список викликаних об’єктів; найчастіше це будуть класи. Кожен виклик приймає рядок, що містить шлях, і або повертає об’єкт імпортера, який оброблятиме імпорт із цього шляху, або викликає виняток ImportError, якщо він не може обробити цей шлях.

  • sys.path_importer_cache кешує об’єкти імпортера для кожного шляху, тому sys.path_hooks потрібно буде пройти лише один раз для кожного шляху.

  • sys.meta_path - це список об’єктів імпортера, які будуть проходити перед перевіркою sys.path. Спочатку цей список порожній, але код користувача може додавати до нього об’єкти. Додаткові вбудовані та заморожені модулі можуть бути імпортовані об’єктом, доданим до цього списку.

Об’єкти імпортера повинні мати єдиний метод, find_module(fullname, path=None). fullname буде назвою модуля або пакета, наприклад. string або distutils.core. find_module() має повертати об’єкт завантажувача, який має один метод, load_module(fullname), який створює та повертає відповідний об’єкт модуля.

Таким чином, псевдокод для нової логіки імпорту Python виглядає приблизно так (трохи спрощено; подробиці див. PEP 302):

for mp in sys.meta_path:
    loader = mp(fullname)
    if loader is not None:
        <module> = loader.load_module(fullname)

for path in sys.path:
    for hook in sys.path_hooks:
        try:
            importer = hook(path)
        except ImportError:
            # ImportError, so try the other path hooks
            pass
        else:
            loader = importer.find_module(fullname)
            <module> = loader.load_module(fullname)

# Not found!
raise ImportError

Дивись також

PEP 302 - Нові хуки імпорту

Автори: Джаст ван Россум і Пол Мур. Реалізовано Юстом ван Россумом.

PEP 305: Файли, розділені комами

Файли, розділені комами, — це формат, який часто використовується для експорту даних із баз даних і електронних таблиць. Python 2.3 додає аналізатор для файлів, розділених комами.

Формат, розділений комами, на перший погляд оманливо простий:

Costs,150,200,3.95

Прочитати рядок і викликати line.split(','): що може бути простіше? Але додайте рядкові дані, які можуть містити коми, і все стане складнішим:

"Costs",150,200,3.95,"Includes taxes, shipping, and sundry items"

Великий потворний регулярний вираз може проаналізувати це, але використання нового пакета csv набагато простіше:

import csv

input = open('datafile', 'rb')
reader = csv.reader(input)
for line in reader:
    print line

Функція reader() має кілька різних параметрів. Роздільник полів не обмежується комою, його можна замінити будь-яким символом, а також символами лапок і кінця рядка.

Можна визначати та реєструвати різні діалекти файлів, розділених комами; наразі існує два діалекти, обидва використовуються Microsoft Excel. Окремий клас csv.writer генеруватиме файли, розділені комами, із послідовності кортежів або списків, цитуючи рядки, які містять роздільник.

Дивись також

PEP 305 - API файлів CSV

Написали та реалізували Кевін Алтіс, Дейв Коул, Ендрю Макнамара, Скіп Монтанаро, Кліфф Веллс.

PEP 307: Поліпшення соління

Модулі pickle і cPickle отримали деяку увагу протягом циклу розробки 2.3. У 2.2 класи нового стилю можна було маринувати без труднощів, але вони не були дуже компактно мариновані; PEP 307 цитує тривіальний приклад, коли клас нового стилю призводить до маринованого рядка втричі довшого, ніж у класичного класу.

Вихід полягав у винаході нового протоколу маринування. Функція pickle.dumps() довгий час підтримувала текстовий або бінарний прапор. У версії 2.3 цей прапорець змінено з логічного значення на ціле: 0 — це старий текстовий формат pickle, 1 — старий двійковий формат, а тепер 2 — це новий формат, специфічний для 2.3. Нову константу, pickle.HIGHEST_PROTOCOL, можна використовувати для вибору найбільш модного доступного протоколу.

Розбирання більше не вважається безпечною операцією. pickle версії 2.2 містить перехоплювачі для спроб запобігти видаленню небезпечних класів (зокрема, атрибут __safe_for_unpickling__), але жоден із цього коду ніколи не перевірявся, тому його було вилучено у 2.3 . Ви не повинні видаляти ненадійні дані в будь-якій версії Python.

Щоб зменшити накладні витрати на травлення для класів нового стилю, було додано новий інтерфейс для налаштування травлення за допомогою трьох спеціальних методів: __getstate__(), __setstate__() та __getnewargs__(). Зверніться до PEP 307 для повної семантики цих методів.

Щоб ще більше стиснути pickles, тепер можна використовувати цілі коди замість довгих рядків для ідентифікації маринованих класів. Python Software Foundation підтримуватиме список стандартизованих кодів; також є ряд кодів для приватного використання. Наразі коди не вказано.

Дивись також

PEP 307 - Розширення протоколу pickle

Написано та реалізовано Гвідо ван Россумом і Тімом Пітерсом.

Розширені зрізи

Починаючи з Python 1.4, синтаксис нарізки підтримує додатковий третій аргумент «крок» або «крок». Наприклад, це законний синтаксис Python: L[1:10:2], L[:-1:1], L[::-1]. Це було додано до Python на прохання розробників Numerical Python, який широко використовує третій аргумент. Однак вбудовані типи списків, кортежів і послідовностей рядків Python ніколи не підтримували цю функцію, викликаючи TypeError, якщо ви спробували її. Майкл Хадсон вніс патч для усунення цього недоліку.

Наприклад, тепер ви можете легко витягти елементи списку, які мають парні індекси:

>>> L = range(10)
>>> L[::2]
[0, 2, 4, 6, 8]

Від’ємні значення також працюють для створення копії того самого списку у зворотному порядку:

>>> L[::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

Це також працює для кортежів, масивів і рядків:

>>> s='abcd'
>>> s[::2]
'ac'
>>> s[::-1]
'dcba'

Якщо у вас є змінна послідовність, наприклад список або масив, ви можете призначити або видалити розширений фрагмент, але є деякі відмінності між призначенням розширеному та звичайному фрагментам. Призначення звичайному фрагменту можна використовувати для зміни довжини послідовності:

>>> a = range(3)
>>> a
[0, 1, 2]
>>> a[1:3] = [4, 5, 6]
>>> a
[0, 4, 5, 6]

Розширені фрагменти не такі гнучкі. Під час призначення розширеному фрагменту список у правій частині оператора має містити таку ж кількість елементів, як і фрагмент, який він замінює:

>>> a = range(4)
>>> a
[0, 1, 2, 3]
>>> a[::2]
[0, 2]
>>> a[::2] = [0, -1]
>>> a
[0, 1, -1, 3]
>>> a[::2] = [0,1,2]
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ValueError: attempt to assign sequence of size 3 to extended slice of size 2

Видалення простіше:

>>> a = range(4)
>>> a
[0, 1, 2, 3]
>>> a[::2]
[0, 2]
>>> del a[::2]
>>> a
[1, 3]

Тепер також можна передавати об’єкти фрагментів до методів __getitem__() вбудованих послідовностей:

>>> range(10).__getitem__(slice(0, 5, 2))
[0, 2, 4]

Або використовуйте об’єкти фрагментів безпосередньо в нижніх індексах:

>>> range(10)[slice(0, 5, 2)]
[0, 2, 4]

Щоб спростити реалізацію послідовностей, які підтримують розширене зрізання, об’єкти зрізів тепер мають метод indices(length), який, враховуючи довжину послідовності, повертає кортеж (start, stop, step), який можна передати безпосередньо до range(). indices() обробляє пропущені та поза межами індекси у спосіб, що відповідає звичайним фрагментам (і ця нешкідлива фраза приховує купу заплутаних деталей!). Метод призначений для використання таким чином:

class FakeSeq:
    ...
    def calc_item(self, i):
        ...
    def __getitem__(self, item):
        if isinstance(item, slice):
            indices = item.indices(len(self))
            return FakeSeq([self.calc_item(i) for i in range(*indices)])
        else:
            return self.calc_item(i)

З цього прикладу ви також можете побачити, що вбудований об’єкт slice тепер є об’єктом типу для типу зрізу, і більше не є функцією. Це узгоджується з Python 2.2, де int, str тощо зазнали тих самих змін.

Інші зміни мови

Ось усі зміни, внесені Python 2.3 до основної мови Python.

  • Оператор yield тепер завжди є ключовим словом, як описано в розділі PEP 255: Прості генератори цього документа.

  • Було додано нову вбудовану функцію enumerate(), як описано в розділі PEP 279: enumerate() цього документа.

  • Дві нові константи, True і False було додано разом із вбудованим типом bool, як описано в розділі PEP 285: логічний тип цього документа.

  • Конструктор типу int() тепер повертатиме довге ціле число замість того, щоб викликати OverflowError, коли рядок або число з плаваючою комою занадто велике, щоб поміститися в ціле число. Це може призвести до парадоксального результату, що isinstance(int(expression), int) є хибним, але це навряд чи викличе проблеми на практиці.

  • Вбудовані типи тепер підтримують розширений синтаксис нарізки, як описано в розділі Розширені зрізи цього документа.

  • Нова вбудована функція, sum(iterable, start=0), додає числові елементи в ітераційному об’єкті та повертає їхню суму. sum() приймає лише числа, тобто ви не можете використовувати його для об’єднання рядків. (Надав Алекс Мартеллі.)

  • list.insert(pos, value) використовувався для вставки value на початку списку, коли pos було від’ємним. Поведінку тепер змінено для узгодження з індексуванням фрагментів, тому, коли pos дорівнює -1, значення буде вставлено перед останнім елементом і так далі.

  • list.index(value), який шукає value у списку та повертає його індекс, тепер приймає додаткові аргументи start і stop, щоб обмежити пошук лише частиною списку.

  • У словниках є новий метод, pop(key[, *default*]), який повертає значення, що відповідає key, і видаляє цю пару ключ/значення зі словника. Якщо потрібний ключ відсутній у словнику, повертається default, якщо його вказано, і KeyError, якщо його немає.

    >>> d = {1:2}
    >>> d
    {1: 2}
    >>> d.pop(4)
    Traceback (most recent call last):
      File "stdin", line 1, in ?
    KeyError: 4
    >>> d.pop(1)
    2
    >>> d.pop(1)
    Traceback (most recent call last):
      File "stdin", line 1, in ?
    KeyError: 'pop(): dictionary is empty'
    >>> d
    {}
    >>>
    

    Існує також новий метод класу, dict.fromkeys(iterable, value), який створює словник із ключами, взятими з наданого ітератора iterable, і всіма значеннями, встановленими на value, за умовчанням None .

    (Патчі надав Раймонд Геттінгер.)

    Крім того, конструктор dict() тепер приймає аргументи ключових слів для спрощення створення невеликих словників:

    >>> dict(red=1, blue=2, green=3, black=4)
    {'blue': 2, 'black': 4, 'green': 3, 'red': 1}
    

    (Надав Джаст ван Россум.)

  • Оператор assert більше не перевіряє прапорець __debug__, тому ви більше не можете вимкнути твердження, призначивши __debug__. Запуск Python із перемикачем -O усе одно генеруватиме код, який не виконує жодних тверджень.

  • Більшість об’єктів типу тепер можна викликати, тому ви можете використовувати їх для створення нових об’єктів, таких як функції, класи та модулі. (Це означає, що модуль new може бути застарілим у майбутній версії Python, оскільки тепер ви можете використовувати об’єкти типу, доступні в модулі types.) Наприклад, ви можете створити новий модуль об’єкт із таким кодом:

    >>> import types
    >>> m = types.ModuleType('abc','docstring')
    >>> m
    <module 'abc' (built-in)>
    >>> m.__doc__
    'docstring'
    
  • Було додано нове попередження PendingDeprecationWarning, щоб вказати на функції, які перебувають у процесі припинення підтримки. За замовчуванням попередження не друкуватиметься. Щоб перевірити використання функцій, які в майбутньому будуть припинені, укажіть -Walways::PendingDeprecationWarning:: у командному рядку або скористайтеся warnings.filterwarnings().

  • Процес припинення винятків на основі рядків, як у підвищення "Сталася помилка", розпочато. Підвищення рядка тепер ініціює PendingDeprecationWarning.

  • Використання None як назви змінної тепер призведе до попередження SyntaxWarning. У майбутній версії Python None може нарешті стати ключовим словом.

  • Метод xreadlines() файлових об’єктів, представлений у Python 2.1, більше не потрібен, оскільки файли тепер поводяться як власний ітератор. xreadlines() спочатку було представлено як швидший спосіб циклічного перегляду всіх рядків у файлі, але тепер ви можете просто написати for line in file_obj. Файлові об’єкти також мають новий атрибут encoding, доступний лише для читання, який надає кодування, яке використовується файлом; Рядки Unicode, записані у файл, будуть автоматично перетворені на байти з використанням заданого кодування.

  • The method resolution order used by new-style classes has changed, though you’ll only notice the difference if you have a really complicated inheritance hierarchy. Classic classes are unaffected by this change. Python 2.2 originally used a topological sort of a class’s ancestors, but 2.3 now uses the C3 algorithm as described in the paper «A Monotonic Superclass Linearization for Dylan». To understand the motivation for this change, read Michele Simionato’s article «Python 2.3 Method Resolution Order», or read the thread on python-dev starting with the message at https://mail.python.org/pipermail/python-dev/2002-October/029035.html. Samuele Pedroni first pointed out the problem and also implemented the fix by coding the C3 algorithm.

  • Python запускає багатопотокові програми, перемикаючись між потоками після виконання N байт-кодів. Значення за замовчуванням для N було збільшено з 10 до 100 байт-кодів, що прискорює однопотокові програми за рахунок зменшення накладних витрат на перемикання. Деякі багатопотокові програми можуть страждати від повільнішого часу відповіді, але це легко виправити, установивши обмеження на нижче значення за допомогою sys.setcheckinterval(N). Обмеження можна отримати за допомогою нової функції sys.getcheckinterval().

  • Одна незначна, але далекосяжна зміна полягає в тому, що назви типів розширень, визначені модулями, що входять до складу Python, тепер містять модуль і '.' перед назвою типу. Наприклад, у Python 2.2, якщо ви створили сокет і надрукували його __class__, ви отримаєте такий результат:

    >>> s = socket.socket()
    >>> s.__class__
    <type 'socket'>
    

    У 2.3 ви отримаєте наступне:

    >>> s.__class__
    <type '_socket.socket'>
    
  • Одну із зазначених несумісностей між класами старого та нового стилів було видалено: тепер ви можете призначати атрибути __name__ та __bases__ класів нового стилю. Існують деякі обмеження щодо того, що можна призначити __bases__ відповідно до тих, що стосуються присвоєння атрибуту __class__ примірника.

Зміни рядків

  • Оператор in тепер працює інакше для рядків. Раніше під час обчислення X в Y, де X і Y є рядками, X міг бути лише одним символом. Тепер це змінилося; X може бути рядком будь-якої довжини, і X в Y поверне True, якщо X є підрядком Y. Якщо X є порожнім рядком, результат завжди буде True.

    >>> 'ab' in 'abcd'
    True
    >>> 'ad' in 'abcd'
    False
    >>> '' in 'abcd'
    True
    

    Зауважте, що це не говорить вам, де починається підрядок; якщо вам потрібна ця інформація, скористайтеся методом рядка find().

  • Рядкові методи strip(), lstrip() і rstrip() тепер мають додатковий аргумент для вказівки символів, які потрібно видалити. За замовчуванням усе ще видаляються всі пробіли:

    >>> '   abc '.strip()
    'abc'
    >>> '><><abc<><><>'.strip('<>')
    'abc'
    >>> '><><abc<><><>\n'.strip('<>')
    'abc<><><>\n'
    >>> u'\u4000\u4001abc\u4000'.strip(u'\u4000')
    u'\u4001abc'
    >>>
    

    (Запропоновано Саймоном Бруннінгом і реалізовано Вальтером Дорвальдом.)

  • Рядкові методи startswith() і endswith() тепер приймають від’ємні числа для параметрів start і end.

  • Іншим новим методом рядків є zfill(), спочатку функція в модулі string. zfill() доповнює числовий рядок нулями зліва, доки він не досягне заданої ширини. Зауважте, що оператор % все ще більш гнучкий і потужніший, ніж zfill().

    >>> '45'.zfill(4)
    '0045'
    >>> '12345'.zfill(4)
    '12345'
    >>> 'goofy'.zfill(6)
    '0goofy'
    

    (Надав Вальтер Дьорвальд.)

  • Додано новий об’єкт типу basestring. І 8-бітні рядки, і рядки Unicode успадковують цей тип, тому isinstance(obj, basestring) поверне True для будь-якого типу рядка. Це повністю абстрактний тип, тому ви не можете створити екземпляри basestring.

  • Внутрішні рядки більше не є безсмертними і тепер збиратимуть сміття у звичайний спосіб, якщо єдине посилання на них міститься у внутрішньому словнику інтернованих рядків. (Реалізовано Ореном Тірошем.)

Оптимізації

  • Створення екземплярів класу нового стилю стало набагато швидшим; тепер вони швидше, ніж класичні заняття!

  • Метод sort() для об’єктів списку був значною мірою переписаний Тімом Пітерсом, і реалізація значно швидша.

  • Множення великих довгих цілих чисел тепер набагато швидше завдяки реалізації множення Карацуби, алгоритму, який масштабується краще, ніж O(n*n), необхідний для алгоритму множення початкової школи. (Оригінальний патч Крістофера А. Крейга та значно перероблений Тімом Пітерсом.)

  • Код операції SET_LINENO тепер зник. Це може забезпечити невелике збільшення швидкості, залежно від особливостей вашого компілятора. Перегляньте розділ Інші зміни та виправлення для більш детального пояснення. (Вилучено Майклом Хадсоном.)

  • Об’єкти xrange() тепер мають власний ітератор, що робить for i in xrange(n) трохи швидшим, ніж for i in range(n). (Патч від Реймонда Геттінгера.)

  • У різних гарячих точках було зроблено ряд невеликих змін, щоб покращити продуктивність, як-от вбудовування функції або видалення деякого коду. (Реалізовано переважно GvR, але багато людей внесли окремі зміни.)

Кінцевим результатом оптимізації 2.3 є те, що Python 2.3 виконує тест pystone приблизно на 25% швидше, ніж Python 2.2.

Нові, покращені та застарілі модулі

Як завжди, стандартна бібліотека Python отримала низку вдосконалень і виправлень помилок. Ось неповний список найбільш помітних змін, відсортованих за алфавітом назв модулів. Зверніться до файлу Misc/NEWS у дереві вихідних кодів, щоб отримати більш повний список змін, або перегляньте журнали CVS, щоб отримати всі деталі.

  • Модуль array тепер підтримує масиви символів Unicode з використанням символу формату 'u'. Масиви також тепер підтримують використання оператора призначення += для додавання вмісту іншого масиву та оператора призначення *= для повторення масиву. (Надав Джейсон Орендорф.)

  • The bsddb module has been replaced by version 4.1.6 of the PyBSDDB package, providing a more complete interface to the transactional features of the BerkeleyDB library.

    Стару версію модуля було перейменовано на bsddb185 і більше не створюється автоматично; вам доведеться відредагувати Modules/Setup, щоб увімкнути його. Зауважте, що новий пакет bsddb призначений для сумісності зі старим модулем, тому обов’язково повідомляйте про помилки, якщо виявите будь-яку несумісність. Під час оновлення до Python 2.3, якщо новий інтерпретатор скомпільовано з новою версією основної бібліотеки BerkeleyDB, вам майже напевно доведеться конвертувати файли вашої бази даних у нову версію. Ви можете зробити це досить легко за допомогою нових скриптів db2pickle.py і pickle2db.py, які ви знайдете в каталозі Tools/scripts дистрибутива. Якщо ви вже використовували пакет PyBSDDB та імпортували його як bsddb3, вам доведеться змінити ваші оператори import, щоб імпортувати його як bsddb.

  • Новий модуль bz2 є інтерфейсом до бібліотеки стиснення даних bz2. bz2-стиснуті дані зазвичай менші за відповідні zlib-стиснуті дані. (Надав Густаво Німейєр.)

  • У новий модуль datetime додано набір стандартних типів дати/часу. Перегляньте наступний розділ для отримання додаткової інформації.

  • Клас Distutils Extension тепер підтримує додатковий аргумент конструктора під назвою depends для переліку додаткових вихідних файлів, від яких залежить розширення. Це дозволяє Distutils перекомпілювати модуль, якщо будь-який із файлів залежностей змінено. Наприклад, якщо sampmodule.c містить файл заголовка sample.h, ви повинні створити об’єкт Extension таким чином:

    ext = Extension("samp",
                    sources=["sampmodule.c"],
                    depends=["sample.h"])
    

    Зміна sample.h призведе до перекомпіляції модуля. (Надав Джеремі Гілтон.)

  • Інші незначні зміни в Distutils: тепер він перевіряє змінні середовища CC, CFLAGS, CPP, LDFLAGS і CPPFLAGS, використовуючи їх, щоб замінити налаштування в конфігурації Python (надано Робертом Вебером).

  • Раніше модуль doctest шукав лише тестові рядки загальнодоступних методів і функцій, але тепер він перевіряє й приватні. Функція DocTestSuite() створює об’єкт unittest.TestSuite з набору тестів doctest.

  • Нова функція gc.get_referents(object) повертає список усіх об’єктів, на які посилається object.

  • Модуль getopt отримав нову функцію, gnu_getopt(), яка підтримує ті самі аргументи, що й існуюча функція getopt(), але використовує режим сканування у стилі GNU. Існуючий getopt() припиняє обробку параметрів, щойно зустрічається аргумент, що не є параметром, але в режимі стилю GNU обробка продовжується, тобто параметри та аргументи можуть змішуватися. Наприклад:

    >>> getopt.getopt(['-f', 'filename', 'output', '-v'], 'f:v')
    ([('-f', 'filename')], ['output', '-v'])
    >>> getopt.gnu_getopt(['-f', 'filename', 'output', '-v'], 'f:v')
    ([('-f', 'filename'), ('-v', '')], ['output'])
    

    (Надав Пітер Естранд.)

  • Модулі grp, pwd і resource тепер повертають розширені кортежі:

    >>> import grp
    >>> g = grp.getgrnam('amk')
    >>> g.gr_name, g.gr_gid
    ('amk', 500)
    
  • Модуль gzip тепер може обробляти файли розміром понад 2 ГіБ.

  • Новий модуль heapq містить реалізацію алгоритму черги купи. Купа — це масивоподібна структура даних, яка зберігає елементи в частково відсортованому порядку, щоб для кожного індексу k «купа[k] <= купа[2*k+1]» і «купа[ k] <= купа[2*k+2]``. Це дозволяє швидко видалити найменший елемент, а вставити новий елемент, зберігаючи властивість купи, становить O(lg n). (Див. https://xlinux.nist.gov/dads//HTML/priorityque.html, щоб дізнатися більше про структуру даних пріоритетної черги.)

    Модуль heapq надає функції heappush() і heappop() для додавання та видалення елементів, зберігаючи при цьому властивість купи поверх іншого змінного типу послідовності Python. Ось приклад використання списку Python:

    >>> import heapq
    >>> heap = []
    >>> for item in [3, 7, 5, 11, 1]:
    ...    heapq.heappush(heap, item)
    ...
    >>> heap
    [1, 3, 5, 11, 7]
    >>> heapq.heappop(heap)
    1
    >>> heapq.heappop(heap)
    3
    >>> heap
    [5, 7, 11]
    

    (Надав Кевін О’Коннор.)

  • Інтегроване середовище розробки IDLE оновлено за допомогою коду проекту IDLEfork (http://idlefork.sourceforge.net). Найбільш помітною особливістю є те, що код, який розробляється, тепер виконується у підпроцесі, що означає, що більше немає потреби в ручних операціях reload(). Код ядра IDLE було включено до стандартної бібліотеки як пакет idlelib.

  • Модуль imaplib тепер підтримує IMAP через SSL. (Пірс Лаудер і Тіно Ланге.)

  • itertools містить низку корисних функцій для використання з ітераторами, натхненними різними функціями, наданими мовами ML і Haskell. Наприклад, itertools.ifilter(predicate, iterator) повертає всі елементи в ітераторі, для яких функція predicate() повертає True, і itertools.repeat(obj, N) повертає obj N разів. У модулі є ряд інших функцій; подробиці див. у довідковій документації пакета. (Надав Реймонд Геттінгер.)

  • Дві нові функції в модулі math, degrees(rads) і radians(degs), конвертують між радіанами та градусами. Інші функції в модулі math, такі як math.sin() і math.cos(), завжди вимагали вхідних значень, виміряних у радіанах. Також до math.log() було додано необов’язковий аргумент base, щоб полегшити обчислення логарифмів для основ, відмінних від e і 10. (Надав Реймонд Геттінгер.)

  • Кілька нових функцій POSIX (getpgid(), killpg(), lchown(), loadavg(), major(), makedev(), minor() і mknod()) були додані до модуля posix, який лежить в основі модуля os. (Надано Густаво Німейєром, Гертом Янсеном і Денісом С. Откидачем.)

  • У модулі os сімейство функцій *stat() тепер може повідомляти частки секунди в мітці часу. Такі мітки часу представлені як числа з плаваючою точкою, подібні до значення, яке повертає time.time().

    Під час тестування було виявлено, що деякі програми працюватимуть з ладу, якщо мітки часу будуть плаваючими. Для сумісності під час використання інтерфейсу кортежу позначки часу stat_result будуть представлені як цілі числа. Під час використання іменованих полів (функція, вперше представлена в Python 2.2), мітки часу все ще представлені як цілі числа, якщо тільки os.stat_float_times() не викликається, щоб увімкнути значення, що повертаються:

    >>> os.stat("/tmp").st_mtime
    1034791200
    >>> os.stat_float_times(True)
    >>> os.stat("/tmp").st_mtime
    1034791200.6335014
    

    У Python 2.4 значення за замовчуванням зміниться на завжди повертати числа з плаваючою точкою.

    Розробникам програм слід увімкнути цю функцію, лише якщо всі їхні бібліотеки працюють належним чином, коли вони стикаються з мітками часу з плаваючою комою, або якщо вони використовують API кортежу. У разі використання цю функцію слід активувати на рівні програми, а не намагатися ввімкнути її для кожного окремого використання.

  • Модуль optparse містить новий синтаксичний аналізатор аргументів командного рядка, який може конвертувати значення параметрів у певний тип Python і автоматично генеруватиме повідомлення про використання. Перегляньте наступний розділ для отримання додаткової інформації.

  • Старий і ніколи не задокументований модуль linuxaudiodev було визнано застарілим і додано нову версію під назвою ossaudiodev. Модуль було перейменовано, тому що звукові драйвери OSS можна використовувати на платформах, відмінних від Linux, і інтерфейс також було впорядковано та оновлено різними способами. (Надано Грегом Уордом і Ніколасом ФітцРой-Дейлом.)

  • Новий модуль platform містить ряд функцій, які намагаються визначити різні властивості платформи, на якій ви працюєте. Є функції для отримання архітектури, типу ЦП, версії ОС Windows і навіть версії дистрибутива Linux. (Надав Марк-Андре Лембург.)

  • Об’єкти синтаксичного аналізатора, надані модулем pyexpat, тепер можуть додатково буферизувати символьні дані, що призводить до меншої кількості викликів вашого обробника символьних даних і, отже, до швидшої роботи. Встановлення атрибута buffer_text об’єкта парсера на True увімкне буферизацію.

  • До модуля random додано функцію sample(population, k). population — це послідовність або об’єкт xrange, що містить елементи сукупності, а sample() вибирає k елементів із сукупності без заміни вибраних елементів. k може бути будь-яким значенням до len(population). Наприклад:

    >>> days = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'St', 'Sn']
    >>> random.sample(days, 3)      # Choose 3 elements
    ['St', 'Sn', 'Th']
    >>> random.sample(days, 7)      # Choose 7 elements
    ['Tu', 'Th', 'Mo', 'We', 'St', 'Fr', 'Sn']
    >>> random.sample(days, 7)      # Choose 7 again
    ['We', 'Mo', 'Sn', 'Fr', 'Tu', 'St', 'Th']
    >>> random.sample(days, 8)      # Can't choose eight
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
      File "random.py", line 414, in sample
          raise ValueError, "sample larger than population"
    ValueError: sample larger than population
    >>> random.sample(xrange(1,10000,2), 10)   # Choose ten odd nos. under 10000
    [3407, 3805, 1505, 7023, 2401, 2267, 9733, 3151, 8083, 9195]
    

    Модуль random тепер використовує новий алгоритм, Mersenne Twister, реалізований у C. Він швидший і детальніше вивчений, ніж попередній алгоритм.

    (Усі зміни внесено Реймондом Геттінгером.)

  • Модуль readline також отримав низку нових функцій: get_history_item(), get_current_history_length() і redisplay().

  • Модулі rexec і Bastion оголошено мертвими, і спроби їх імпортувати будуть невдалими з RuntimeError. Класи нового стилю надають нові способи виходу з обмеженого середовища виконання, наданого rexec, і ніхто не зацікавлений у їх виправленні чи часу для цього. Якщо у вас є програми, які використовують rexec, перепишіть їх, щоб використовувати щось інше.

    (Дотримання Python 2.2 або 2.1 не зробить ваші програми безпечнішими, оскільки в модулі rexec у цих версіях є відомі помилки. Повторюю: якщо ви використовуєте rexec, припиніть його використовувати негайно.)

  • Модуль rotor застарів, оскільки алгоритм, який він використовує для шифрування, вважається небезпечним. Якщо вам потрібне шифрування, скористайтеся одним із кількох модулів AES Python, які доступні окремо.

  • Модуль shutil отримав функцію move(src, dest), яка рекурсивно переміщує файл або каталог до нового розташування.

  • Підтримку вдосконаленої обробки сигналів POSIX було додано до signal, але потім знову вилучено, оскільки виявилося неможливим забезпечити його надійну роботу на різних платформах.

  • Модуль socket тепер підтримує тайм-аути. Ви можете викликати метод settimeout(t) для об’єкта сокета, щоб встановити час очікування t секунд. Подальші операції з сокетом, які тривають більше t секунд, перериваються та викликають виняток socket.timeout.

    Оригінальна реалізація тайм-ауту була створена Тімом О’Меллі. Майкл Гілфікс інтегрував його в модуль Python socket і перевірив його через довгий огляд. Після перевірки коду Гвідо ван Россум переписав його частини. (Це хороший приклад процесу спільної розробки в дії.)

  • У Windows модуль socket тепер поставляється з підтримкою Secure Sockets Layer (SSL).

  • Значення макросу C PYTHON_API_VERSION тепер доступне на рівні Python як sys.api_version. Поточний виняток можна очистити, викликавши нову функцію sys.exc_clear().

  • Новий модуль tarfile дозволяє читати та записувати в архівні файли у форматі tar. (Надав Ларс Густебель.)

  • Новий модуль textwrap містить функції для обтікання рядків, що містять абзаци тексту. Функція wrap(text, width) приймає рядок і повертає список, що містить текст, розбитий на рядки шириною не більше вибраного. Функція fill(text, width) повертає один рядок, переформатований, щоб поміститися в рядки, довжина яких не перевищує вибрану ширину. (Як ви можете здогадатися, fill() створено на основі wrap(). Наприклад:

    >>> import textwrap
    >>> paragraph = "Not a whit, we defy augury: ... more text ..."
    >>> textwrap.wrap(paragraph, 60)
    ["Not a whit, we defy augury: there's a special providence in",
     "the fall of a sparrow. If it be now, 'tis not to come; if it",
     ...]
    >>> print textwrap.fill(paragraph, 35)
    Not a whit, we defy augury: there's
    a special providence in the fall of
    a sparrow. If it be now, 'tis not
    to come; if it be not to come, it
    will be now; if it be not now, yet
    it will come: the readiness is all.
    >>>
    

    Модуль також містить клас TextWrapper, який фактично реалізує стратегію обтікання текстом. Як клас TextWrapper, так і функції wrap() і fill() підтримують низку додаткових ключових аргументів для точного налаштування форматування; подробиці дивіться в документації модуля. (Надав Грег Ворд.)

  • Модулі thread і threading тепер мають супутні модулі, dummy_thread і dummy_threading, які забезпечують бездіяльну реалізацію модуля thread інтерфейс для платформ, де потоки не підтримуються. Намір полягає в тому, щоб спростити модулі з підтримкою потоків (ті, які не покладаються на виконання потоків), розмістивши наступний код у верхній частині:

    try:
        import threading as _threading
    except ImportError:
        import dummy_threading as _threading
    

    У цьому прикладі _threading використовується як назва модуля, щоб зрозуміти, що використовуваний модуль не обов’язково є справжнім модулем threading. Код може викликати функції та використовувати класи в _threading незалежно від того, підтримуються потоки чи ні, уникаючи оператора if і роблячи код трохи зрозумілішим. Цей модуль магічним чином не змусить багатопоточний код працювати без потоків; код, який чекає, поки інший потік повернеться або щось зробить, просто зависне назавжди.

  • Функція strptime() модуля time вже давно викликає роздратування, оскільки вона використовує реалізацію strptime() бібліотеки платформи C, і на різних платформах іноді трапляються дивні помилки. Бретт Кеннон зробив внесок у портативну реалізацію, яка написана на чистому Python і має однаково працювати на всіх платформах.

  • Новий модуль timeit допомагає виміряти, скільки часу потрібно для виконання фрагментів коду Python. Файл timeit.py можна запустити безпосередньо з командного рядка, або клас Timer модуля можна імпортувати та використовувати безпосередньо. Ось короткий приклад, який показує, чи можна швидше перетворити 8-бітний рядок на Unicode, додавши до нього порожній рядок Unicode або використовуючи функцію unicode():

    import timeit
    
    timer1 = timeit.Timer('unicode("abc")')
    timer2 = timeit.Timer('"abc" + u""')
    
    # Run three trials
    print timer1.repeat(repeat=3, number=100000)
    print timer2.repeat(repeat=3, number=100000)
    
    # On my laptop this outputs:
    # [0.36831796169281006, 0.37441694736480713, 0.35304892063140869]
    # [0.17574405670166016, 0.18193507194519043, 0.17565798759460449]
    
  • Модуль Tix отримав різні виправлення помилок і оновлення для поточної версії пакета Tix.

  • Модуль Tkinter тепер працює з версією Tcl з підтримкою потоків. Потокова модель Tcl вимагає, щоб доступ до віджетів здійснювався лише з потоку, в якому вони створені; доступ з іншого потоку може спричинити паніку Tcl. Для певних інтерфейсів Tcl Tkinter тепер автоматично уникатиме цього, коли доступ до віджету здійснюється з іншого потоку, розподіляючи команду, передаючи її правильному потоку та чекаючи на результати. Інші інтерфейси не можна обробляти автоматично, але Tkinter тепер створить виняток для такого доступу, щоб ви могли принаймні дізнатися про проблему. Дивіться https://mail.python.org/pipermail/python-dev/2002-December/031107.html для більш детального пояснення цієї зміни. (Реалізовано Мартіном фон Льовісом.)

  • Виклик методів Tcl через _tkinter більше не повертає лише рядки. Натомість, якщо Tcl повертає інші об’єкти, ці об’єкти перетворюються на їхній еквівалент Python, якщо такий існує, або загортаються в об’єкт _tkinter.Tcl_Obj, якщо еквівалент Python не існує. Цією поведінкою можна керувати за допомогою методу wantobjects() об’єктів tkapp.

    Під час використання _tkinter через модуль Tkinter (як у більшості програм Tkinter), ця функція завжди активна. Це не повинно викликати проблем із сумісністю, оскільки Tkinter завжди перетворюватиме результати рядків у типи Python, де це можливо.

    Якщо буде виявлено будь-яку несумісність, стару поведінку можна відновити, встановивши для змінної wantobjects у модулі Tkinter значення false перед створенням першого об’єкта tkapp.

    import Tkinter
    Tkinter.wantobjects = 0
    

    Будь-яку поломку, спричинену цією зміною, слід повідомити як помилку.

  • Модуль UserDict має новий клас DictMixin, який визначає всі методи словника для класів, які вже мають мінімальний інтерфейс відображення. Це значно спрощує написання класів, які мають бути замінними словниками, наприклад класів у модулі shelve.

    Додавання суміші як суперкласу надає повний інтерфейс словника щоразу, коли клас визначає __getitem__(), __setitem__(), __delitem__() та keys(). Наприклад:

    >>> import UserDict
    >>> class SeqDict(UserDict.DictMixin):
    ...     """Dictionary lookalike implemented with lists."""
    ...     def __init__(self):
    ...         self.keylist = []
    ...         self.valuelist = []
    ...     def __getitem__(self, key):
    ...         try:
    ...             i = self.keylist.index(key)
    ...         except ValueError:
    ...             raise KeyError
    ...         return self.valuelist[i]
    ...     def __setitem__(self, key, value):
    ...         try:
    ...             i = self.keylist.index(key)
    ...             self.valuelist[i] = value
    ...         except ValueError:
    ...             self.keylist.append(key)
    ...             self.valuelist.append(value)
    ...     def __delitem__(self, key):
    ...         try:
    ...             i = self.keylist.index(key)
    ...         except ValueError:
    ...             raise KeyError
    ...         self.keylist.pop(i)
    ...         self.valuelist.pop(i)
    ...     def keys(self):
    ...         return list(self.keylist)
    ...
    >>> s = SeqDict()
    >>> dir(s)      # See that other dictionary methods are implemented
    ['__cmp__', '__contains__', '__delitem__', '__doc__', '__getitem__',
     '__init__', '__iter__', '__len__', '__module__', '__repr__',
     '__setitem__', 'clear', 'get', 'has_key', 'items', 'iteritems',
     'iterkeys', 'itervalues', 'keylist', 'keys', 'pop', 'popitem',
     'setdefault', 'update', 'valuelist', 'values']
    

    (Надав Реймонд Геттінгер.)

  • Реалізація DOM у xml.dom.minidom тепер може генерувати вивід XML у певному кодуванні, надаючи необов’язковий аргумент кодування для методів toxml() і toprettyxml() вузлів DOM.

  • Модуль xmlrpclib тепер підтримує розширення XML-RPC для обробки нульових значень даних, таких як None Python. Нульові значення завжди підтримуються при демаршалінгу відповіді XML-RPC. Щоб генерувати запити, які містять None, ви повинні вказати справжнє значення для параметра allow_none під час створення екземпляра Marshaller.

  • The new DocXMLRPCServer module allows writing self-documenting XML-RPC servers. Run it in demo mode (as a program) to see it in action. Pointing the Web browser to the RPC server produces pydoc-style documentation; pointing xmlrpclib to the server allows invoking the actual methods. (Contributed by Brian Quinlan.)

  • Додано підтримку інтернаціоналізованих доменних імен (RFC 3454, 3490, 3491 і 3492). Кодування «idna» можна використовувати для перетворення між доменним іменем Unicode і ASCII-сумісним кодуванням (ACE) цього імені.

    >{}>{}> u"www.Alliancefrançaise.nu".encode("idna")
    'www.xn--alliancefranaise-npb.nu'
    

    Модуль socket також було розширено, щоб прозоро конвертувати імена хостів Unicode у версію ACE перед передачею їх до бібліотеки C. Модулі, що працюють з іменами хостів, наприклад httplib і ftplib), також підтримують імена хостів Unicode; httplib також надсилає заголовки HTTP Host, використовуючи версію ACE доменного імені. urllib підтримує Unicode URL-адреси з іменами хостів, відмінними від ASCII, якщо частина URL-адреси path містить лише ASCII.

    Для впровадження цієї зміни було додано модуль stringprep, інструмент mkstringprep і кодування punycode.

Тип дати/часу

Типи дати та часу, придатні для вираження позначок часу, були додані як модуль datetime. Типи не підтримують різні календарі чи багато модних функцій і лише дотримуються основ представлення часу.

Три основні типи: date, що представляє день, місяць і рік; time, що складається з години, хвилини та секунди; і datetime, який містить усі атрибути як date, так і time. Існує також клас timedelta, що представляє різницю між двома точками в часі, а логіка часового поясу реалізована класами, що успадковують абстрактний клас tzinfo.

Ви можете створити екземпляри date і time, надавши аргументи ключового слова у відповідний конструктор, наприклад. datetime.date(year=1972, month=10, day=15) або за допомогою одного з методів класу. Наприклад, метод класу date.today() повертає поточну місцеву дату.

Після створення екземпляри класів дати/часу залишаються незмінними. Існує кілька методів створення форматованих рядків з об’єктів:

>>> import datetime
>>> now = datetime.datetime.now()
>>> now.isoformat()
'2002-12-30T21:27:03.994956'
>>> now.ctime()  # Only available on date, datetime
'Mon Dec 30 21:27:03 2002'
>>> now.strftime('%Y %d %b')
'2002 30 Dec'

Метод replace() дозволяє змінювати одне або більше полів екземпляра date або datetime, повертаючи новий екземпляр:

>>> d = datetime.datetime.now()
>>> d
datetime.datetime(2002, 12, 30, 22, 15, 38, 827738)
>>> d.replace(year=2001, hour = 12)
datetime.datetime(2001, 12, 30, 12, 15, 38, 827738)
>>>

Екземпляри можна порівнювати, хешувати та перетворювати на рядки (результат такий самий, як у isoformat()). Екземпляри date і datetime можна відняти один від одного та додати до екземплярів timedelta. Найбільша відсутня функція полягає в тому, що немає стандартної підтримки бібліотеки для аналізу рядків і повернення date або datetime.

Для отримання додаткової інформації зверніться до довідкової документації модуля. (Надав Тім Пітерс.)

Модуль optparse

Модуль getopt забезпечує простий аналіз аргументів командного рядка. Новий модуль optparse (початкова назва Optik) забезпечує більш детальний аналіз командного рядка, який відповідає умовам Unix, автоматично створює вихід для --help і може виконувати різні дії для різних параметрів .

Ви починаєте зі створення екземпляра OptionParser і повідомляєте йому, які параметри вашої програми.

import sys
from optparse import OptionParser

op = OptionParser()
op.add_option('-i', '--input',
              action='store', type='string', dest='input',
              help='set input filename')
op.add_option('-l', '--length',
              action='store', type='int', dest='length',
              help='set maximum length of output')

Розбір командного рядка потім виконується викликом методу parse_args().

options, args = op.parse_args(sys.argv[1:])
print options
print args

Це повертає об’єкт, що містить усі значення параметрів, і список рядків, що містять решту аргументів.

Виклик сценарію з різними аргументами тепер працює так, як ви очікували. Зауважте, що аргумент довжини автоматично перетворюється на ціле число.

$ ./python opt.py -i data arg1
<Values at 0x400cad4c: {'input': 'data', 'length': None}>
['arg1']
$ ./python opt.py --input=data --length=4
<Values at 0x400cad2c: {'input': 'data', 'length': 4}>
[]
$

Довідкове повідомлення генерується для вас автоматично:

$ ./python opt.py --help
usage: opt.py [options]

options:
  -h, --help            show this help message and exit
  -iINPUT, --input=INPUT
                        set input filename
  -lLENGTH, --length=LENGTH
                        set maximum length of output
$

Додаткову інформацію дивіться в документації модуля.

Optik був написаний Грегом Уордом із пропозиціями читачів Getopt SIG.

Pymalloc: спеціалізований розподільник об’єктів

Pymalloc, спеціалізований розподільник об’єктів, написаний Володимиром Марангозовим, був функцією, доданою до Python 2.1. Pymalloc має бути швидшим за системний malloc() і мати менше витрат пам’яті для шаблонів розподілу, типових для програм Python. Розподільник використовує функцію C malloc(), щоб отримати великі пули пам’яті, а потім виконує менші запити пам’яті з цих пулів.

У версіях 2.1 і 2.2 pymalloc був експериментальною функцією і не був увімкнений за замовчуванням; ви повинні були явно ввімкнути його під час компіляції Python, надавши опцію --with-pymalloc сценарію configure. У версії 2.3 pymalloc отримав додаткові вдосконалення, і тепер він увімкнено за замовчуванням; вам доведеться вказати --without-pymalloc, щоб вимкнути його.

Ця зміна прозора для коду, написаного на Python; однак pymalloc може виявити помилки в розширеннях C. Автори модулів розширення C повинні протестувати свій код із увімкненим pymalloc, оскільки деякий неправильний код може спричинити дамп ядра під час виконання.

Є одна особливо поширена помилка, яка викликає проблеми. В API C Python є кілька функцій розподілу пам’яті, які раніше були лише псевдонімами malloc() і free() бібліотеки C, тобто якщо ви випадково викликали невідповідні функції, помилка не було б помітно. Коли розподільник об’єктів увімкнено, ці функції більше не є псевдонімами malloc() і free(), і виклик неправильної функції для звільнення пам’яті може призвести до створення дампа ядра. Наприклад, якщо пам’ять було виділено за допомогою PyObject_Malloc(), її потрібно звільнити за допомогою PyObject_Free(), а не free(). Кілька модулів, що входять до складу Python, вийшли з ладу, і їх потрібно було виправити; безсумнівно, є інші сторонні модулі, які матимуть таку саму проблему.

У рамках цієї зміни незрозумілі кілька інтерфейсів для розподілу пам’яті були об’єднані у дві сімейства API. Пам’яттю, виділеною для одного сімейства, не можна маніпулювати функціями з іншого сімейства. Існує одне сімейство для розподілу фрагментів пам’яті та інше сімейство функцій спеціально для розподілу об’єктів Python.

  • Щоб виділити та звільнити нерозрізнену частину пам’яті, використовуйте сімейство «необробленої пам’яті»: PyMem_Malloc(), PyMem_Realloc() і PyMem_Free().

  • Сімейство «об’єктної пам’яті» є інтерфейсом до описаного вище засобу pymalloc і спрямоване на велику кількість «маленьких» розподілів: PyObject_Malloc(), PyObject_Realloc() і PyObject_Free().

  • Щоб виділити та звільнити об’єкти Python, використовуйте сімейство «об’єктів» PyObject_New(), PyObject_NewVar() і PyObject_Del().

Завдяки великій роботі Тіма Пітерса, pymalloc у версії 2.3 також надає функції налагодження для виявлення перезапису пам’яті та подвійного звільнення в обох модулях розширення та в самому інтерпретаторі. Щоб увімкнути цю підтримку, скомпілюйте версію інтерпретатора Python для налагодження, запустивши configure з --with-pydebug.

Щоб допомогти розробникам розширень, файл заголовка Misc/pymemcompat.h поширюється разом із джерелом для Python 2.3, який дозволяє розширенням Python використовувати інтерфейси 2.3 для розподілу пам’яті під час компіляції з будь-якою версією Python, починаючи з 1.5.2. Ви повинні скопіювати файл із вихідного коду Python і об’єднати його з джерелом вашого розширення.

Дивись також

https://hg.python.org/cpython/file/default/Objects/obmalloc.c

Щоб отримати повну інформацію про реалізацію pymalloc, перегляньте коментарі у верхній частині файлу Objects/obmalloc.c у вихідному коді Python. Наведене вище посилання вказує на файл у браузері python.org SVN.

Зміни збірки та C API

Зміни в процесі збирання Python і в API C включають:

  • Реалізація виявлення циклу, яка використовується для збирання сміття, виявилася стабільною, тому тепер вона стала обов’язковою. Ви більше не можете скомпілювати Python без нього, а перемикач --with-cycle-gc на configure видалено.

  • Python тепер можна опціонально створити як спільну бібліотеку (libpython2.3.so), вказавши --enable-shared під час виконання сценарію configure Python. (Надав Ондрей Палковський.)

  • Макроси DL_EXPORT і DL_IMPORT тепер застаріли. Функції ініціалізації для модулів розширення Python тепер слід оголошувати за допомогою нового макросу PyMODINIT_FUNC, тоді як ядро Python зазвичай використовуватиме макроси PyAPI_FUNC і PyAPI_DATA.

  • Інтерпретатор може бути скомпільований без будь-яких рядків документації для вбудованих функцій і модулів, надаючи --without-doc-strings до сценарію configure. Це робить виконуваний файл Python приблизно на 10% меншим, але також означатиме, що ви не зможете отримати допомогу для вбудованих компонентів Python. (Надав Густаво Німейєр.)

  • Макрос PyArg_NoArgs() більше не підтримується, а код, який його використовує, слід змінити. Для Python 2.2 і пізніших версій таблиця визначення методів може вказати прапорець METH_NOARGS, сигналізуючи про те, що аргументів немає, і тоді перевірку аргументів можна видалити. Якщо важлива сумісність із версіями Python до 2.2, замість цього код може використовувати PyArg_ParseTuple(args, ""), але це буде повільніше, ніж використання METH_NOARGS.

  • PyArg_ParseTuple() accepts new format characters for various sizes of unsigned integers: B for unsigned char, H for unsigned short int, I for unsigned int, and K for unsigned long long.

  • Нову функцію PyObject_DelItemString(mapping, char *key) було додано як скорочення для PyObject_DelItem(mapping, PyString_New(key)).

  • Файлові об’єкти тепер керують своїм внутрішнім рядковим буфером по-іншому, збільшуючи його експоненціально за потреби. Це призводить до значного прискорення тестів у Lib/test/test_bufio.py (з 57 секунд до 1,7 секунд, згідно з одним вимірюванням).

  • Тепер можна визначити класові та статичні методи для типу розширення C, встановивши прапорці METH_CLASS або METH_STATIC у структурі методу PyMethodDef.

  • Python тепер містить копію вихідного коду синтаксичного аналізатора Expat XML, усуваючи будь-яку залежність від версії системи або локальної інсталяції Expat.

  • Якщо ви динамічно розподіляєте об’єкти типу у своєму розширенні, ви повинні знати про зміну правил, що стосуються атрибутів __module__ і __name__. Таким чином, ви захочете переконатися, що словник типу містить ключ '__module__'; створення назви модуля частиною назви типу, що веде до останньої крапки, більше не матиме бажаного ефекту. Щоб отримати докладніші відомості, прочитайте довідкову документацію API або джерело.

Зміни, що стосуються порту

Підтримку перенесення на OS/2 IBM за допомогою середовища виконання EMX було об’єднано в основне дерево вихідних кодів Python. EMX — це рівень емуляції POSIX над API системи OS/2. Порт Python для EMX намагається підтримувати всі POSIX-подібні можливості, надані середовищем виконання EMX, і здебільшого вдається; fork() і fcntl() обмежені обмеженнями основного рівня емуляції. Стандартний порт OS/2, який використовує компілятор IBM Visual Age, також отримав підтримку семантики імпорту з урахуванням регістру в рамках інтеграції порту EMX у CVS. (Надав Ендрю Макінтайр.)

У MacOS більшість модулів панелі інструментів були слабко зв’язані, щоб покращити зворотну сумісність. Це означає, що модулі більше не будуть завантажуватися, якщо в поточній версії ОС відсутня одна процедура. Натомість виклик відсутньої підпрограми призведе до виключення. (Надав Джек Янсен.)

Файли специфікацій RPM, знайдені в каталозі Misc/RPM/ вихідного коду Python, було оновлено до версії 2.3. (Надав Шон Райфшнайдер.)

Інші нові платформи, які зараз підтримуються Python, включають AtheOS (http://www.atheos.cx/), GNU/Hurd і OpenVMS.

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

Як завжди, була купа інших покращень і виправлень помилок, розкиданих по дереву вихідних кодів. Пошук у журналах змін CVS виявив, що між Python 2.2 і 2.3 було застосовано 523 виправлення та 514 виправлених помилок. Обидві цифри, ймовірно, занижені.

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

  • Якщо встановлено змінну середовища PYTHONINSPECT, інтерпретатор Python увійде в інтерактивну підказку після запуску програми Python, як якщо б Python було викликано з параметром -i. Змінну середовища можна встановити перед запуском інтерпретатора Python або її можна встановити програмою Python як частину її виконання.

  • Сценарій regrtest.py тепер надає спосіб дозволити «всі ресурси, крім foo». Ім’я ресурсу, передане параметру -u, тепер може мати перед префіксом дефіс ('-'), що означає «видалити цей ресурс». Наприклад, параметр «-uall,-bsddb» можна використовувати, щоб увімкнути використання всіх ресурсів, крім bsddb.

  • Інструменти, які використовуються для створення документації, тепер працюють як під Cygwin, так і під Unix.

  • Код операції SET_LINENO видалено. У давнину цей код операції був потрібний для створення номерів рядків у відстеженнях і підтримки функцій відстеження (наприклад, для pdb). Починаючи з Python 1.5, номери рядків у трасуваннях обчислюються за допомогою іншого механізму, який працює з «python -O». Для Python 2.3 Майкл Хадсон реалізував подібну схему, щоб визначити, коли викликати функцію трасування, повністю усунувши потребу в SET_LINENO.

    Було б важко виявити будь-яку результуючу відмінність від коду Python, окрім невеликого прискорення, коли Python запускається без -O.

    Розширення C, які мають доступ до поля f_lineno об’єктів фрейму, мають замість цього викликати PyCode_Addr2Line(f->f_code, f->f_lasti). Це матиме додатковий ефект, оскільки код працюватиме за бажанням під «python -O» у попередніх версіях Python.

    Чудовою новою функцією є те, що функції трасування тепер можуть призначати атрибут f_lineno об’єктів фрейму, змінюючи рядок, який буде виконано наступним. Команда jump була додана до налагоджувача pdb, використовуючи цю нову функцію. (Реалізовано Річі Гіндлом.)

Перенесення на Python 2.3

У цьому розділі перераховано описані раніше зміни, які можуть потребувати змін у вашому коді:

  • yield тепер завжди є ключовим словом; якщо воно використовується як ім’я змінної у вашому коді, потрібно вибрати інше ім’я.

  • Для рядків X і Y «X в Y» тепер працює, якщо X містить більше одного символу.

  • Конструктор типу int() тепер повертатиме довге ціле число замість того, щоб викликати OverflowError, коли рядок або число з плаваючою комою занадто велике, щоб поміститися в ціле число.

  • Якщо у вас є рядки Unicode, які містять 8-бітові символи, ви повинні оголосити кодування файлу (UTF-8, Latin-1 або інше), додавши коментар у верхній частині файлу. Перегляньте розділ PEP 263: Кодування вихідного коду для отримання додаткової інформації.

  • Виклик методів Tcl через _tkinter більше не повертає лише рядки. Натомість, якщо Tcl повертає інші об’єкти, ці об’єкти перетворюються на їхній еквівалент Python, якщо такий існує, або загортаються в об’єкт _tkinter.Tcl_Obj, якщо еквівалент Python не існує.

  • Великі вісімкові та шістнадцяткові літерали, такі як 0xffffffff, тепер викликають FutureWarning. Наразі вони зберігаються як 32-розрядні числа та отримують від’ємне значення, але в Python 2.4 вони стануть додатними довгими цілими числами.

    Є кілька способів виправити це попередження. Якщо вам справді потрібне позитивне число, просто додайте L до кінця літералу. Якщо ви намагаєтеся отримати 32-розрядне ціле число з установленими молодшими бітами і раніше використовували такий вираз, як ~(1 << 31), ймовірно, найзрозуміліше почати з усіма встановленими бітами та очистити потрібний верхній біти. Наприклад, щоб очистити лише верхній біт (біт 31), ви можете написати 0xffffffffL &~(1L<<31).

  • Ви більше не можете вимкнути твердження, призначивши __debug__.

  • Функція Distutils setup() отримала різні нові ключові аргументи, такі як depends. Старі версії Distutils перериваються, якщо передано невідомі ключові слова. Рішенням є перевірка наявності нової функції get_distutil_options() у вашому setup.py і використання нових ключових слів лише з версією Distutils, яка їх підтримує:

    from distutils import core
    
    kw = {'sources': 'foo.c', ...}
    if hasattr(core, 'get_distutil_options'):
        kw['depends'] = ['foo.h']
    ext = Extension(**kw)
    
  • Використання None як назви змінної тепер призведе до попередження SyntaxWarning.

  • Назви типів розширень, визначені модулями, що входять до Python, тепер містять модуль і '.' перед назвою типу.

Подяки

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