Partial string formatting?

Jeff Epler jepler at unpythonic.net
Tue Jan 21 17:41:39 EST 2003


I'd like to mention one more potential problem with this "partial
formatting" idea.  It seems that you wish to take a string through
multiple formatting steps.  But what about the following format string?
    "%(item)s is %(frac)d%% as hard as glass."
after the first formatting step, it might look like this:
    "%(item)s is 37% as hard as glass."
but when you format again, you'll get an error, because "% " is not a
proper format specifier.

You can run into a variation of this problem if the formatted thing
contains a %.  For instance:
    "The symbol '%(sym)s' is spelled out as '%(word)s'."
becoming
    "The symbol '%' is spelled out as '%(word)s'."

I think this question must be addressed if your goal is truly to do
incremental formatting.  For instance, you might use a wrapper class (or
string subclass) so that the % operator updates an internal dict, and the
__str__ method returns the string formatted with the current internal dict:

(Note that my earlier 'format' function doesn't work in the presence of
'%%', either.  The __str__ method of IncrementallyFormattedString seems to,
though.  It still won't properly handle other weird stuff, such as the
legal-but-unlikely '%(%)s')

Jeff

class IncrementallyFormattedString:
    def __init__(self, s, d={}):
	self.s = s
	self.d = d.copy()

    def __str__(self):
	s = self.s
	d = self.d
	i = s.find("%")
	out = [s[:i]]
	while 1:
	    if s[i:i+2] == "%%":
		out.append("%")
		i=i+2
		continue
	    j = s.find("%", i+1)
	    if j == -1:
		try:
		    out.append(s[i:] % d)
		except KeyError:
		    out.append(s[i:])
		break
	    #print "__str__", i, j, s[i:j]
	    try:
		out.append(s[i:j] % d)
	    except KeyError:
		out.append(s[i:j])
	    i = j
	return "".join(out)


    def __mod__(self, d):
	d = d.copy()
	d.update(self.d)
	return IncrementallyFormattedString(self.s, d)

I = IncrementallyFormattedString

s = I("%(item)s is %(frac)d%% as hard as glass.")
s = s % {'frac': 37}
print s
s = s % {'item': 'Spam'}
print s

s = I("The symbol '%(sym)s' is spelled out as '%(word)s'.")
s = s % {'sym': '%'}
print s
s = s % {'word': 'percent'}
print s





More information about the Python-list mailing list