Сообщить об ошибке.

Текстовые константы и шаблоны, модуль string

Исходный код можно найти: Lib/string.py

Многие функции, ранее реализованные в модуле string, были перенесены в методы объектов str. Модуль string сохраняет несколько полезных констант и классов для работы с объектами str.

Пользовательское форматирование строки.

Класс string.Formatter в модуле string позволяет создавать и настраивать собственное поведение форматирования строк, используя ту же реализацию, что и встроенный метод str.format().

В большинстве случаев встроенный метод str.format() класса str представляет собой более удобный интерфейс для функций форматирования переменных, но класс Formatter модуля string предоставляется способ создания подклассов для случаев, когда требуются изменения в способе форматирования.

Шаблонные строки.

Шаблоны строк предназначены в качестве альтернативы встроенному синтаксису замены переменных при форматировании строк. При интерполяции строки по шаблону string.Template переменные идентифицируются с помощью префикса $, например, $var. В качестве альтернативы, если необходимо выделить их из окружающего текста, они также могут быть обернуты фигурными скобками, например ${var}.

import string

values = {'one': 'Привет', 'two': 'коп'}

t = string.Template("""
Просто переменная: $one
Экранируем префикс: $$
Переменная в тексте: квадро${two}тер.
""")

print(t.substitute(values))
# Просто переменная: Привет
# Экранируем знак доллара: $
# Переменная в тексте: квадрокоптер.

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

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

import string

values = {'var': 'foo'}

t = string.Template("$var is here but $missing is not provided")
try:
    print('substitute():', t.substitute(values))
except KeyError as err:
    print('ERROR:', str(err))

print('safe_substitute():', t.safe_substitute(values))
# ERROR: 'missing'
# safe_substitute(): foo is here but $missing is not provided

Так как в словаре values отсутствует значение для переменной шаблона $missing, то вызывается исключение KeyError при использовании метода шаблона substitute(). Метод safe_substitute(), вместо того, чтобы вызвать ошибку ловит ее и оставляет выражение переменной в тексте.

Расширенное использование шаблонов.

Синтаксис по умолчанию для string.Template можно изменить, заменив их шаблонами на основе регулярных выражений, которые будут использоваться для поиска имен переменных в теле шаблона. Простой способ сделать это-изменить разделитель delimiter и атрибут класса idpattern.

import string

class MyTemplate(string.Template):
    delimiter = '%'
    idpattern = '[a-z]+_[a-z]+'

template_text = '''
  Delimiter : %%
  Replaced  : %with_underscore
  Ignored   : %notunderscored
'''

d = {'with_underscore': 'replaced', 'notunderscored': 'not replaced'}

t = MyTemplate(template_text)
print(t.safe_substitute(d))
#  Delimiter : %
#  Replaced  : replaced
#  Ignored   : %notunderscored

В примере правила подстановки изменены таким образом, что разделителем является % вместо $, а имена переменных должны содержать символ подчеркивания. Из примера видно, что шаблон %notunderscored - без подчеркивания ничем не заменяется.

Для еще более сложных изменений можно переопределить атрибут pattern и задать совершенно новое регулярное выражение. Атрибут pattern должен содержать четыре именованные группы: escaped - для захвата экранированного разделителя, именованную переменную named, фигурную версию имени переменной braced и недопустимые шаблоны разделителя invalid. (Подробнее смотрите описание класса string.Template(template))

Стандартный атрибут pattern можно получить следующим способом:

import string

t = string.Template('$var')
print(t.pattern.pattern)
# \$(?:
#   (?P<escaped>\$) |
#   (?P<named>[_a-z][_a-z0-9]*) |
#   {(?P<braced>[_a-z][_a-z0-9]*)} |
#   (?P<invalid>)
# )

Определим новый шаблон для использования {{var}} в качестве синтаксиса переменной.

import re
import string

# Переопределяем delimiter и pattern
class NewTemplate(string.Template):
    delimiter = '{{'
    pattern = r'''
    \{\{(?:
    (?P<escaped>\{\{) |
    (?P<named>[_a-z][_a-z0-9]*)\}\} |
    (?P<braced>[_a-z][_a-z0-9]*)\}\} |
    (?P<invalid>)
    )
    '''

t = NewTemplate('''Привет {{var}}!''')
print(t.safe_substitute(var='Мир'))
# Привет Мир!