Язык программирования Python - что нового в 2.1

Автор: Олег Бройтман
http://phd.pp.ru/
phd@phd.pp.ru

Это шестая статья данного цикла лекций, и вторая, рассказывающая, что нового в последних версиях Питона.

Перепечатка. Оригинал статьи опубликован по адресу http://www.softerra.ru/review/oses/linux/15430/

Как я уже говорил в предыдущей статье, развитие Питона идет такими темпами, что версии 2.1 и 2.2 следовало бы назвать 3.0 и 4.0.

Python 2.1

Первое гигантское изменение в версии 2.1 - вложенные области видимости имен (nested scopes), пока еще опционально. В предыдущих версиях любая функция, даже описанная как вложенная, не имела доступа к локальном переменным объемлющей функции, а только к глобальным переменным модуля. Людям, писавшим на C это понятно - там вообще нет вложенных функций. Но имеющим опыт программирования на Паскале и подобных языках это совсем непонятно. Кончилось это введением вложенных пространств имен. Правда, эти вложенные пространства имеют доступ на чтение из внутренний области, но не могут связывать переменные во внешней области - связывание переменных можно осуществлять только локально. Тем не менее и этого достаточно, чтобы создавать замыкания (closures) - функции, результатом работы которых являются функции, помнящие свой контекст. Например:

def makeAdder(n):
   def adder(x):
      return x+n
   return adder # каждая копия adder помнит свое значение n!
Результатом вызова функции makeAdder(3) будет функция, которая увеличивает свой аргумент на 3:
add3 = makeAdder(3)
print add3(12) # => 15

Такое кардинальное изменение породило среди пользователей опасение, что их код (в котором раньше не было никаких намеков на вложенные области видимости) может сломаться. Для того чтобы не делать резкого перехода, разработчики решили ввести в Питон возможность создавать опциональные конструкции, которые бы программист мог включать по желанию, для того, чтобы проверить свой код, а в последующих версиях эти конструкции уже полностью войдут в язык. Так, вложенные пространства имен включаются кодом from __future__ import nested_scopes. Надо отметить, что __future__ - не настоящий модуль, а указание компилятору включить новую функциональность там, где __future__ импортируется.

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

Следующее большое новшество в этой версии - "богатое" сравнение (rich comparison). В предыдущих версиях программист, желающий переопределить операцию сравнения для своих классов, мог написать метод __cmp__, который мог вернуть 0, 1 или -1 и ничего другого. Этот метод не мог даже вызвать исключения. Такое узкое понимание сравнения недостаточно даже для сравнения матриц, не говоря уже о чем-то более сложном. Python 2.1 решает эту проблему - программисту предоставляется возможность переопределить по своему усмотрению каждую операцию сравнения (< <=; > >= == !=). Операция сравнения может вернуть что угодно - не только признак 0/1/-1, но вообще любой объект - список, матрицу и т.д. Можно также возбудить исключение, сигнализировав, что сравнение невозможно.

"Слабые ссылки" - это ссылки, которые автоматически удаляются, если на объект нет других ссылок. Это позволяет создавать циклы ссылок, которые будут автоматически разрываться и освобождать память.

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

Каждый модуль теперь сам может управлять, какие именно имена будут из него проимпортированы командой from module import * - просто перечислите все имена в глобальном списке __all__.

В механизме компиляции в этой версии Питона появилось автоопределение библиотек, установленных на компьютере. Раньше программист (или, точнее, администратор, устанавливающий Питон) должен был включить необходимые модули в файле конфигурации Modules/Setup. Теперь же скрипт setup.py сам выполняет необходимую работу.

В библиотеке появились новые модули. Inspect.py и pydoc.py позволяют заглянуть во внутренности модуля и сгенерировать документацию для него. Два новых модуля для генерации тестов - doctest и pyunit. Модуль difflib позволяет сравнить 2 последовательности, например 2 последовательности строк из текстовых файлов, и сгенерировать список отличий между ними. Новая версия PyXML поддерживает Expat 1.2. Модуль ftplib теперь по умолчанию работает в пассивном режиме. Модуль socket приобрел поддержку raw sockets. Существенно ускорено построчное чтение текстовых файлов; новый модуль xreadlines ориентирован на построчное чтение; его достоинство - "ленивое" чтение - он не загружает в память все строки файла, но в тоже время позволяет писать цикл for line in xreadlines(fileobj)...

Хотя это и не относится непосредственно к языку, интерпретатору или библиотеке, все же это важная новость. PEP241 вводит механизм метаданных, описывающих пакет. Distutils генерирует эти метаданные, и это позволяет приступить к создания глобального репозитория модулей.

Python 2.0.1 и 2.1.1

Уже после выхода Python 2.1 вышел bugfix к версии 2.0 - 2.0.1. А потом был и bugfix к 2.1 - версия 2.1.1. Помимо исправленных ошибок начиная с этих версий изменилась лицензия - она стала GPL-совместимой (но все еще не GPL). Это позволяет распространять Питон совместно с программами и модулями, защищенными лицензией GPL!