Исходный код можно найти: 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='Мир')) # Привет Мир!