Есть шаблон строки, который я хочу заполнить значениями за два (или за N) вызова str.format()
:
template = 'foo{a}bar{b}buzz'
Сначала так:
step1 = template.format(a=' A ') print (step1) > foo A bar{b}buzz
Потом:
step2 = step1.format(b=' B ') print(step2) > foo A bar B
Однако Python не позволяет передать в format()
список меньшего размера или словарь не со всеми значениями.
Можно ли как-то выполнить «каррирование», то есть частичный str.format()
? (Я понимаю, что это совсем не каррирование, поэтому кавычки. Grundy подсказывает, что это можно называть «частичным применением»).
Разумеется, я могу сделать так:
'foo{a}bar{b}buzz'.format(a=' A ', b='{b}')
Но это грязный хак, мне он не нравится тем, что нужно каждый раз перечислять параметры, то есть способ не универсален.
Ещё можно использовать чистое каррирование и создавать промежуточный объект-метод. Но он не является строкой, его нельзя передать в какой-то сторонний метод, который ждет именно строку.
Интересны решения для Python2 и Python 3.
В данном случае нужно не каррирование, а частичное применение.
Для этого используется функция partial
из модуля functools
например:
from functools import partial template = 'foo{a}bar{b}buzz'; fun = partial(template.format, a='w'); print( fun(b='dd') );
Если в форматируемой строке подставляемые значения обрамлены пробелами, как в вопросе, то удобно использовать `string.Template’.
from string import Template temp = Template('foo $a bar $b buzz') temp.safe_substitute(a='test') >>> 'foo test bar $b buzz' temp.substitute(a='test', b='val') >>> 'foo test bar val buzz'
Если пробелов не должно быть, то уже не так красиво и надо учитывать, могут ли быть пробелы в подставляемой строке, или выбрать другой разделитель в Template
:
strfmt = 'foo{}bar{}buzz' temp = Template('$a $b') strfmt.format(*temp.safe_substitute(a='TEST').split())