Все хорошо знают об операторе форматирования в языке Python. В этой заметке приводятся малоизвестные приемы его использования.
В самом простом способе применения оператора форматирования его поведение аналогично функций *printf в C:
>>> print Длина удава: %d попугаев и %d попугайское крылышко % (38, 1) Длина удава: 38 попугаев и 1 попугайское крылышко
При использовании %s или %r объекты любого типа автоматически преобразуются к строке, как если бы к ним применялась функция str или repr соответственно:
>>> print Длина удава: %s попугаев и %s попугайское крылышко % (38, 1) Длина удава: 38 попугаев и 1 попугайское крылышко
Для длинных строк с большим количеством параметров удобнее ссылаться на значения по имени. Это позволит менять порядок следования значений в строке не меняя правый аргумент оператора форматирования:
>>> args = {parrots: 38, wings: 1} >>> print %(parrots)s попугаев и %(wings)s попугайское крылышко % args 38 попугаев и 1 попугайское крылышко >>> print %(wings)s крылышко в добавок к %(parrots)s попугаям % args 1 крылышко в добавок к 38 попугаям >>> print %(wings)s крылышко не в счет % args 1 крылышко не в счет
Можно не составлять словарь самостоятельно, а использовать функцию globals, locals или vars:
>>> print %(parrots)s попугаев и %(wings)s попугайское крылышко % vars() 38 попугаев и 1 попугайское крылышко
Однако и это не все, что можно делать с оператором форматирования. Тем, кто знаком с языком perl, обычно сильно не достает интерполяции строк с выражениями, записанными непосредственно в строке-шаблоне. Аналогичный эффект можно получить и в языке Python с помощью простого классом, имитирующего поведение словаря:
class EvalDict: def __getitem__(self, key): return eval(key)
Использовать класс EvalDict можно аналогично функции vars:
>>> nums = [38, 1] >>> print %(nums[0])s попугаев и %(nums[1])s крылышко % EvalDict() 38 попугаев и 1 крылышко
Приведенный класс EvalDict обладает двумя недостатками. Во-первых, он ищет значения переменных только в глобальном пространстве имен модуля, в котором он определен. Во-вторых, он не будет обрабатывать вложенные выражения. Исправим эти недостатки.
import sys
class EvalDict:
def __init__(self, globals=None, locals=None): if globals is None: globals = sys._getframe(1).f_globals self.globals = globals if locals is None: locals = sys._getframe(1).f_locals self.locals = locals