partial string formatting
--
Music by Eric Matyas
https://www.soundimage.org
Track title: Light Drops
--
Chapters
00:00 Question
00:25 Accepted answer (Score 72)
00:57 Answer 2 (Score 159)
01:16 Answer 3 (Score 159)
01:40 Answer 4 (Score 63)
03:27 Thank you
--
Full question
https://stackoverflow.com/questions/1128...
Answer 3 links:
[lazy_format]: https://pypi.python.org/pypi/lazy_format
[Template strings]: https://docs.python.org/2/library/string...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #stringformatting
#avk47
ANSWER 1
Score 167
If you know in what order you're formatting things:
s = '{foo} {{bar}}'
Use it like this:
ss = s.format(foo='FOO')
print ss
>>> 'FOO {bar}'
print ss.format(bar='BAR')
>>> 'FOO BAR'
You can't specify foo and bar at the same time - you have to do it sequentially.
ACCEPTED ANSWER
Score 77
You can trick it into partial formatting by overwriting the mapping:
import string
class FormatDict(dict):
def __missing__(self, key):
return "{" + key + "}"
s = '{foo} {bar}'
formatter = string.Formatter()
mapping = FormatDict(foo='FOO')
print(formatter.vformat(s, (), mapping))
printing
FOO {bar}
Of course this basic implementation only works correctly for basic cases.
ANSWER 3
Score 67
This limitation of .format() - the inability to do partial substitutions - has been bugging me.
After evaluating writing a custom Formatter class as described in many answers here and even considering using third-party packages such as lazy_format, I discovered a much simpler inbuilt solution: Template strings
It provides similar functionality but also provides partial substitution thorough safe_substitute() method. The template strings need to have a $ prefix (which feels a bit weird - but the overall solution I think is better).
import string
template = string.Template('${x} ${y}')
try:
template.substitute({'x':1}) # raises KeyError
except KeyError:
pass
# but the following raises no error
partial_str = template.safe_substitute({'x':1}) # no error
# partial_str now contains a string with partial substitution
partial_template = string.Template(partial_str)
substituted_str = partial_template.safe_substitute({'y':2}) # no error
print substituted_str # prints '12'
Formed a convenience wrapper based on this:
class StringTemplate(object):
def __init__(self, template):
self.template = string.Template(template)
self.partial_substituted_str = None
def __repr__(self):
return self.template.safe_substitute()
def format(self, *args, **kws):
self.partial_substituted_str = self.template.safe_substitute(*args, **kws)
self.template = string.Template(self.partial_substituted_str)
return self.__repr__()
>>> s = StringTemplate('${x}${y}')
>>> s
'${x}${y}'
>>> s.format(x=1)
'1${y}'
>>> s.format({'y':2})
'12'
>>> print s
12
Similarly a wrapper based on Sven's answer which uses the default string formatting:
class StringTemplate(object):
class FormatDict(dict):
def __missing__(self, key):
return "{" + key + "}"
def __init__(self, template):
self.substituted_str = template
self.formatter = string.Formatter()
def __repr__(self):
return self.substituted_str
def format(self, *args, **kwargs):
mapping = StringTemplate.FormatDict(*args, **kwargs)
self.substituted_str = self.formatter.vformat(self.substituted_str, (), mapping)
ANSWER 4
Score 29
Not sure if this is ok as a quick workaround, but how about
s = '{foo} {bar}'
s.format(foo='FOO', bar='{bar}')
? :)