20 малоизвестных фич и особенностей Python

5
10683
Добавить в избранное

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

20 малоизвестных фич и особенностей Python

Отладка регулярных выражений

Регулярные выражения Python – мощный и полезный инструмент, но отлаживать их – то еще удовольствие. Оказывается, любую регулярку можно визуализировать в виде дерева синтаксического анализа. Эта возможность языка пока экспериментальная, за нее отвечает флаг re.DEBUG в методе re.compile.

Посмотрим на регулярное выражение для поиска тегов font. С ним что-то не так.

Теперь ясно, что именно. В закрывающем дескрипторе [/font] не экранированы квадратные скобки, поэтому он воспринимается не как тег, а как группа символов.

Выражения-генераторы

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

А еще есть выражения-генераторы, которые не загружают коллекцию в память целиком, а выдают лишь один элемент по требованию. В некоторых случаях это позволяет существенно сэкономить расходы памяти. Единственное отличие в синтаксисе – это круглые скобки:

Ряд особенностей Python генераторов:

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

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

Подводные камни дефолтных аргументов

Устанавливая значение аргументов функции по умолчанию, будьте очень осторожны:

Вряд ли вы хотели, чтобы список x изменялся при каждом вызове функции. Так происходит из-за того, что дефолтные параметры хранятся в неизменном кортеже в атрибуте foo.func_defaults, который создается в момент определения функции.

Вместо мутабельных списков лучше использовать значение None, а список присваивать в x уже внутри функции:

Передача значений в генератор

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

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

В старом стандарте языка был метод my_generator.next(value), который сразу возвращал текущее значение генератора и принимал новое. В Python 3 необходимо использовать два метода: next(my_generator) и my_generator.send(value).

Фигурные скобки

Python использует для форматирования кода не скобки, как C-подобные языки (Java, C#, PHP), а табуляцию. Если такой синтаксис вам непривычен, используйте пакет braces из модуля __future__.

Эта фича очень спорная. Настоящие питонисты возмущены самим наличием подобной Python библиотеки.

Шаг среза

Третий аргумент slice-оператора в Python определяет шаг среза. По умолчанию он равен единице, поэтому в итоговый срез попадают все элементы диапазона подряд.

А можно взять, например, каждый второй элемент:

Если передать третьим параметром -1, счет пойдет в обратном порядке. Так можно легко развернуть список или строку.

Декораторы

Декоратор – это обертка для функции, позволяющая изменить некоторым образом ее поведение. Например, просто распечатать аргументы перед вызовом:

Теперь необходимо передать функции print_args другую функцию, аргументы которой необходимо распечатать:

Все работает правильно, но приходится создавать новую функцию и вызывать именно ее.

В Python работа с декораторами устроена гораздо удобнее. Вы можете сохранить исходное имя функции и ее подпись при интроспеции:

Отсутствующие элементы словарей

В Python 2.5 у словарей появился специальный метод __missing__. Он вызывается при обращении к отсутствующим элементам:

Примерно то же самое делает подкласс defaultdict: он вызывает для несуществующих элементов функцию без аргументов.

Многострочные регулярные выражения

Одна из самых приятных особенностей Python – возможность разбить длинные регулярки на несколько строк, добавить комментарии и сделать их более читаемыми.

Многострочные регулярные выражения Python можно создавать и без re.VERBOSE, используя обычную конкатенацию строчных литералов:

Кроме того, совпадения можно именовать:

Распаковка аргументов

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

Эта фича языка очень полезна, так как в Python списки, кортежи и словари широко используются в качестве контейнеров.

Динамическое создание типов

Программирование на Python допускает создание новых типов прямо во время выполнения программы.

Это то же самое, что и:

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

Метод словарей get

Если вы обратитесь к несуществующему ключу словаря dict[key], то получите исключение. Эту проблему можно решить с помощью метода dict.get(key), который вернет None для несуществующих ключей. Вторым параметром ему можно передать значение по умолчанию:

Это удобно, например, при арифметических операциях.

Дескрипторы

Атрибуты можно превратить в дескрипторы, изменив их стандартное поведение с помощью методов __get__, __set__ или __delete__. Таким образом можно, например, запретить перезапись или удаление свойства.

Создадим такой дескриптор, используя для удобства декоратор:

Теперь при обращении через точку к дескриптору foo, управление передается его методу __get__, который сначала печатает строчку с данными дескриптора, а затем вызывает его «родной» геттер (выполняется код функции foo).

Дескрипторы – довольно сложная фича, но вам стоит разобраться в ней, чтобы глубже понимать как работает язык программирования Python.

Doctest: документация + юнит-тестирование

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

Вот официальный пример работы doctest:

Чтобы увидеть результат, запустите этот модуль прямо из командной строки с флагом -v. Вы получите нечто вроде:

Именованное форматирование строк

В Python 3 для форматирования строк используется метод format:

Передаваемые в строку параметры можно именовать для удобства:

Поиск модулей

Путь поиска импортируемых модулей в Python выглядит так:

  1. Домашний каталог программы, который может отличаться от текущего рабочего каталога
  2. Адреса из переменной окружения PYTHONPATH.
  3. Каталоги стандартной Python библиотеки, которые устанавливаются автоматически.
  4. Директории, перечисленные в *.pth файлах.
  5. Каталог site-packages, в котором автоматически размещаются все сторонние расширения.

try-except-else

В конструкцию try-except можно добавить также блок else. Он отработает только в случае выполнения кода без ошибок:

Использовать блок else предпочтительнее, чем добавлять дополнительный код в блок try. Это позволяет избежать случайного перехвата исключений, которые не были вызваны кодом, защищенным конструкцией try-except.

Ререйз исключений

Применив оператор raise без параметров внутри обработчика ошибок, вы можете повторно «поднять» пойманное исключение с сохранением его оригинальной трассировки стека. Это полезно, если пойманное исключение должно обрабатываться на верхних уровнях программы:

Оригинальную трассировку можно получить с помощью sys.exc_info().

Автодополнение для интерактивного интерпретатора

Одна из немногочисленных неприятных особенностей Python консоли: отсутствие встроенного автодополнения вводимых команд. Эту проблему решает модуль rlcompleter:

Теперь с помощью клавиши TAB вы можете быстро подобрать нужные атрибуты:

import this

Главный священный текст любого питониста всегда даст ценный совет, подкинет полезную идею и подбодрит уставшего разработчика. Просто выполните команду import this.

Надеемся, вы узнали что-то новое о возможностях и особенностях Python. Своими открытиями делитесь в комментариях.

Лучшие материалы и книги по Python

Интересуетесь программированием на Python?

Подпишитесь на нашу рассылку, чтобы получать больше интересных материалов:

И не беспокойтесь, мы тоже не любим спам. Отписаться можно в любое время.




Комментариев: 5

  1. Большое спасибо за статью! Очень много полезной информации!
    По-поводу форматирования строк, в Python 3.6 появился новый способ f-строки, который гибче, читабельней и быстрей. https://www.python.org/dev/peps/pep-0498

    Небольшая опечатка про срез:
    каждый второй элемент:
    print(a[2:8:]) # [3, 5, 7]
    правильно:
    print(a[2:8:2]) # [3, 5, 7]

    Спасибо.

    1. Спасибо за информацию и за внимательность 😉

  2. Nikolay Karelin

    Народ, не позорьтесь…

    Судя по упомянутой версии 2.5 вы перевели что-то старое… и фиг проверяли.

    Например from __future__ import braces давно выдает SyntaxError D)

  3. Дэвид Хэллер

    print(a[2:8:]) # [3, 5, 7]
    Если передать третьим параметром -1, счет пойдет в обратном порядке. Так можно легко развернуть список или строку.

    Опечатка должно быть print(a[2:8:2]) # [3, 5, 7]

    1. Спасибо за внимательность)

Добавить комментарий