Fork me on GitHub
19/9/2006

Наконец то вышел Python 2.5

Наконец дождались релиза новой ветки Python - 2.5. Скачать новую версию можно с официального сайта. Что появилось нового в этой ветке по сравнению с 2.4 можно прочитать в PEP 356 и в документации.

Ниже я кратко рассмотрел основные возможности, добавленные в Python 2.5.

PEP 308: условные выражения

Появился тернарный оператор, теперь код

if condition:
    x = true_value
else:
    x = false_value

можно записать так:

x = true_value if condition else false_value

См. PEP 308 для подробностей.

PEP 309: Частично вычислимые функции

Появился модуль functools, в котором собраны инструменты для программирования в функциональном стиле. Например, функция partial(), позволяет создавать частично вычислимые функции. Т.е. можно создать функцию, на основе существующей, у которой часть аргументов уже определена.

import functools

def log(message, subsystem):
    print "%s: %s" % (subsystem, message)

server_log = functools.partial(log, subsystem='server')
server_log("Unable to open socket")

Подробности см. в PEP 309.

PEP 314: Метаданные для пакетов ПО, версия 1.1

В distutils добавлены зависимости. Теперь в функции setup() есть параметры requires, provides и obsoletes.

VERSION = '1.1'
setup(name='MyPyPackages',
      version=VERSION,
  requires=['numarray', 'zlib (>=1.1.4)'],
  obsoletes=['OldPackages'],
  download_url=('http://example.com/mypypackage/dist/pkg-%s.tar.gz'
                 % VERSION),
)

Помимо этого, добавлена команда upload, которая автоматически загружает пакет на CheeseShop Python Package index.

Подробности по использованию см. в PEP 314.

PEP 328: Абсолютный и относительный импорт

Ранее, если имелся пакет pkg:

pkg/
pkg/__init__.py
pkg/main.py
pkg/string.py

то import string из модуля main импортировал pkg.string, а не стандартный модуль. В будущих версиях (где-то в районе Python 2.7) import string будет всегда импортировать стандартный модуль. Такого поведения (т.е. абсолютный импорт) можно и добиться в Python 2.5, выполнив директиву:

from __future__ import absoulte_import

Так что теперь нужно либо явно импортировать string из пакета pkg:

from pkg import string

Либо воспользоваться относительным импортом:

from . import string

Варианты использования таковы:

# код внутри модуля A.B.C
from . import D # импортирует A.B.D
from .. import E    # импортирует A.E
from ..F import G   # импортирует A.F.G

Поправка: имена, начинающиеся с точки можно использовать только в конструкции from ... import.

Более полную информацию об абсолютном и относительном импорте см. в PEP 328.

PEP 341: Унифицированный try/except/finally

До Python 2.5 try использовался в двух вариантах: либо с finally, либо с except. Теперь можно использовать except и finally одновременно.

try:
    block-1 ...
except Exception1:
    handler-1 ...
except Exception2:
    handler-2
else:
    else-block
finally:
    final-block

Выполняется код block-1. Если во время выполнения возбуждается исключение, то в зависимости от класса исключения (Exception1 либо Exception2) выполняется либо handler-1, либо handler2. Если исключение не возбуждается, то выполняется else-block. И вне зависимости от того, было ли возбуждено исключение и какого типа, выполняется final-block. Даже если в обработчиках были ошибки, или при выполнении else-block было возбуждено исключение, всё равно final-block будет выполнен.

Подробности см. в PEP 341.

PEP 342: Новые возможности генераторов

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

Немного освежим память о генераторах. Например, простой генератор:

def counter(maximum):
    i = 0
    while i < maximum:
        yield i
        i += 1

При вызове counter(10) получаем итератор, возвращающий значения от 0 до 9. Когда итератор наталкивается на yield, он возвращает переданное значение и "замораживает" выполнение функции, сохраняя при этом локальные переменные. Итератор "просыпается" при вызове метода next() и продолжает выполнение функции сразу после yield.

В Python 2.3 yield была инструкцией (statement), в Python 2.5 она стала выражением (expression). Так что теперь она возвращает значение, которое может быть присвоено переменной или другим образом обработано:

val = (yield i)

Ниже приведен переписанный на Python 2.5 пример:

def counter(maximum):
    i = 0
    while i < maximum:
        val = (yield i)
        # если это значение, меняем счетчик
        if val is not None:
            i = val
        else:
            i += 1

И вот так можно передавать значения:

>>> it = counter(10)
>>> print it.next()
0
>>> print it.next()
1
>>> print it.send(8)
8
>>> print it.next()
9
>>> print it.next()
Traceback (most recent call last):
  File ``t.py'', line 15, in ?
    print it.next()
StopIteration

Зачем нужно проверять на None, какие новые методы помимо send() появились у генераторов можно узнать из PEP 342

PEP 343: Инструкция 'with'

Инструкция with делает код более прозрачным в тех случаях, когда использовали try...finally для гарантии выполнения "очищающего" (clean-up) кода.

Для того, чтобы включить эту инструкцию в Python 2.5 необходимо выполнить директиву:

from __future__ import with_statement

Начиная с Python 2.6, инструкция with будет доступна и без этой директивы.

Общая структура кода с инструкцией with выглядит так:

with expression [as variables]:
    with-block

И пример использования:

with open('/etc/passwd', 'r') as f:
    for line in f:
    print line
    ... что-то еще ...

После завершения блока, объект f автоматически будет закрыт, даже если в цикле for было возбуждено исключение.

Другой пример, с блокировками (пакет threading):

lock = threading.Lock()
with lock:
    # критический код
...

Блокировка захватывается до выполнения блока, и в любом случае отпускается после его завершения (удачного или неудачного).

Более подробно об использовании with рассказано в соответствующем разделе документации и в PEP 343.

PEP 352: Исключения - классы нового типа

Во-первых сами исключения стали классами нового типа (new-style class). А во-вторых, изменилась иерархия. Теперь она выглядит примерно так:

BaseException       # новый, появился Python 2.5
|- KeyboardInterrupt
|- SystemExit
|- Exception
   |- (все остальные исключения)

В-третьих, использование строк как исключений (т.е. код raise "Error occurred") будет выдавать предупреждение.

Подробнее об этом см. в PEP 352.

Другие изменения в языке

Изменения, внесенные в язык:

  • В объектах типа dict появился новый магический метод __missing__(key), вызываемый в случае, если ключ key не найден в словаре.

  • К строкам добавлены методы partition(sep) и rpartition(sep) для разбивки строки разделителем

  • Методы startswith() и endswith() строк теперь в качестве аргумента могут принимать кортеж строк, а не только одну строку.

  • Функциям min() и max() теперь можно передавать параметр key (смысл этого параметра аналогичен таковому у sort())

  • Новые встроенные функции any() и all() определяют, содержит ли итератор True и False значения,. any() имеет смысл OR, а all() имеет смысл AND.

  • ACII теперь кодировка по умолчанию для модулей. Так что если не указана кодировка и модуль содержит 8-и битные символы, то Python будет интерпретировать это как ошибку синтаксиса. В Python 2.4 это было лишь предупреждением. Поэтому внимательно читайте PEP 263

  • Добавлено новое предупреждение, UnicodeWarning, возникает в случае сравнения unicode-строки и обычной, 8-и битной. При этом результат сравнения - False. До этого возбуждалось исключение UnicodeDecodeError.

  • Часто Python-программисты забывают добавлять файл __init__.py в каталог, чтобы Python считал это каталог пакетом. Ранее нельзя было импортировать каталог без __init__.py. Сейчас можно. При этом может быть показано предупреждение (по умолчанию оно выключено) ImportWarning.

  • Можно опускать базовый класс в описании класса. Т.е. такой код вполне нормален:

    class C():
           pass
    

Новые модули

В Python 2.5 в стандартную поставку добавились модули:

  • contextlib - вспомогательные функции, используемые с инструкцией with
  • cProfile - C-реализация модуля profile
  • msilib - модуль для создания файлов Microsoft installer .msi и CAB.
  • spwd - модуль для доступа к БД теневых паролей (shadow password), на тех платформах, которые их поддерживают.
  • uuid - модуль для создания универсальных уникальных идентификаторов (UUID) по RFC 4122.
  • ctypes - известный модуль Томаса Хеллера для доступа к бинарным библиотекам (.so, .dll) теперь в составе стандартной библиотеки
  • ElementTree - модуль Фредрика Лундха для обработки XML включен в стандартную поставку под именем xml.etree.
  • hashlib - новый модуль Грегори Смита, пришел на замену md5 и sha. Реализует различные хеши (SHA-224, SHA-256, SHA-512).
  • sqlite3 - давно ожидаемый pysqlite вошел в стандартную библиотеку.
  • wsgiref - модуль, реализующий простой HTTP-сервер с поддержкой WSGI (см. PEP 333)

Комментарии

Все статьи