Расширенное форматирование строк Python с пользовательскими заполнителями?
У меня есть следующий шаблон HTML в переменной Python:
template = """
<script>
function work()
{
alert('bla');
}
</script>
Success rate is {value:.2%} percent.
"""
Я хочу подставить {value:.2%}
некоторым десятичным числом с соответствующим форматированием. Поскольку мой шаблон может содержать много JavaScript-кода, я хочу избежать экранирования фигурных скобок с помощью {{
и }}
, поэтому использование template.format(...)
напрямую не является вариантом.
Использование Template(template).substitute(...)
также представляется невозможным, потому что я хочу расширенное форматирование для value
.
Я мог бы заменить {value:.2%}
соответствующим синтаксисом %(value)...
, а затем использовать template % ...
. Но я не являюсь поклонником этого синтаксиса, потому что для большинства переменных в реальном мире шаблону не требуется расширенное форматирование, поэтому я хочу, чтобы синтаксис заполнителя был простым.
Итак, мой вопрос в том, можно ли использовать шаблоны в шаблоне, которые позволяли бы форматировать при необходимости, т.е. просто {{value}}
или [[value]]
, а также {{value:.2%}}
или [[value:.2%]]
?
Изменить: Наконец, я хочу избежать ошибок, которые создавал бы .format(...)
, когда шаблон содержит заполнители, например {{dont_want_this_substituted}}
, для которых переданный словарь не содержит значения. То есть, я хочу только заменить только определенные заполнители, а не все, что отображается в шаблоне.
Изменить 2: Чтобы добиться того, чего я хочу, я могу сначала захватить все заполнители с помощью регулярного выражения, затем отформатировать их содержимое и, наконец, сделать замену в шаблоне. Но мне интересно, существует ли более простое решение.
Изменить 3: Было предложено разбить шаблон, чтобы избежать проблем с format()
. Однако я хотел бы избежать этого, потому что шаблон фактически исходит из файла.
Ответы
Ответ 1
Просто предварительно обработайте шаблон. Например, если вы хотите, чтобы [[...]]
был вашим маркером шаблона и оставил только одиночные символы {
и }
:
template = """
<script>
function work()
{
alert('bla');
}
</script>
Success rate is [[value:.2%]] percent.
"""
result = template.replace("{", "{{").replace("}", "}}").replace("[[", "{").replace("]]", "}").format(value=0.8675309)
Попытка сделать все это с разным количеством фигурных скобок сложна, поэтому я определенно буду использовать некоторые другие персонажи. Однако осторожно, что такие вещи, как [[
и ]]
, могут иметь место в законном коде JavaScript. Возможно, лучше использовать то, что никогда не могло.
Ответ 2
Забудьте регулярное выражение и предварительную обработку. Вы должны разбить шаблон так, чтобы переменные части не были в той же строке, что и части <script>
.
head = """
<script>
function work()
{
alert('bla');
}
</script>
"""
template = """
{head}
Success rate is {value:.2%} percent.
"""
Наконец, я хочу избежать ошибок, которые будет возникать .format(...), когда шаблон содержит заполнители, такие как {{dont_want_this_substitution}}, для которых переданный словарь не содержит значения. То есть, я хочу только заменить только определенные заполнители, а не все, что отображается в шаблоне.
Это может быть взломано, но вы можете использовать collections.defaultdict
, как показано в этом ответе. Образец кода из этого ответа (изменено).
from collections import defaultdict
my_csv = '{optional[first]},{optional[middle]},{optional[last]}'
print( my_csv.format( optional=defaultdict(str, first='John', last='Doe') ) )