Following a remark here: How to define a new string formatter, I tried subclassing string.Formatter
. Here is what I\'ve done. Unfortunately I seem to have broke
str.format
does auto numbering, while string.Formatter
does not.
Modifying __init__
and overriding get_value
will do the trick.
def __init__(self):
super(CustFormatter, self).__init__()
self.last_number = 0
def get_value(self, key, args, kwargs):
if key == '':
key = self.last_number
self.last_number += 1
return super(CustFormatter, self).get_value(key, args, kwargs)
BTW, above code does not strictly mimic str.format
behavior. str.format
complains if we mix auto numbering with manual number, but above does not.
>>> '{} {1}'.format(1, 2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: cannot switch from automatic field numbering to manual field specification
>>> '{0} {}'.format(1, 2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: cannot switch from manual field specification to automatic field numbering
Good news: you have not done anything wrong.
Bad news: that's how string.Formatter
behaves, it does not support {}
-like positional format. So, the last call will fail even without any subclassing. Good news: that's can be fixed by overriding the parse
method:
import string
class CF(string.Formatter):
def parse(self, s):
position = 0
for lit, name, spec, conv in super(CF, self).parse(s):
if not name:
name = str(position)
position += 1
yield lit, name, spec, conv
Bad news... Ah, no, that's basically it:
>>> CF().format('{} {}!', 'Hello', 'world')
'Hello world!'