[Python-3000] string.Formatter class
Ron Adam
rrr at ronadam.com
Thu Aug 30 13:12:13 CEST 2007
Eric Smith wrote:
> One of the things that PEP 3101 deliberately under specifies is the
> Formatter class, leaving decisions up to the implementation. Now that a
> working implementation exists, I think it's reasonable to tighten it up.
>
> I have checked in a Formatter class that specifies the following methods
> (in addition to the ones already defined in the PEP):
>
> parse(format_string)
> Loops over the format_string and returns an iterable of tuples
> (literal_text, field_name, format_spec, conversion). This is used by
> vformat to break the string in to either literal text, or fields that
> need expanding. If literal_text is None, then expand (field_name,
> format_spec, conversion) and append it to the output. If literal_text
> is not None, append it to the output.
>
> get_field(field_name, args, kwargs, used_args)
> Given a field_name as returned by parse, convert it to an object to be
> formatted. The default version takes strings of the form defined in the
> PEP, such as "0[name]" or "label.title". It records which args have
> been used in used_args. args and kwargs are as passed in to vformat.
Rather than pass the used_args set out and have it modified in a different
methods, I think it would be better to pass the arg_used back along with
the object. That keeps all the code that is involved in checking used args
is in one method. The arg_used value may be useful in other ways as well.
obj, arg_used = self.get_field(field_name, args, kwargs)
used_args.add(arg_used)
> convert_field(value, conversion)
> Converts the value (returned by get_field) using the conversion
> (returned by the parse tuple). The default version understands 'r'
> (repr) and 's' (str).
> Or, define your own conversion character:
> =================
> class XFormatter(Formatter):
> def convert_field(self, value, conversion):
> if conversion == 'x':
> return None
> if conversion == 'r':
> return repr(value)
> if conversion == 's':
> return str(value)
> return value
> fmt = XFormatter()
> print(fmt.format("{0!r}:{0!x}", fmt))
> =================
> which prints:
> <__main__.XFormatter object at 0xf6f6d2cc>:None
I wonder if this is splitting things up a bit too finely? If the format
function takes a conversion argument, it makes it possible to do everything
by overriding format_field.
def format_field(self, value, format_spec, conversion):
return format(value, format_spec, conversion)
Adding this to Talins suggestion, the signature of format could be...
format(value, format_spec="", conversion="")
Then the above example becomes...
class XFormatter(Formatter):
def format_field(self, value, format_spec, conversion):
if conversion == 'x':
return "None"
return format(value, format_spec, conversion)
It just seems cleaner to me.
Cheers,
Ron
More information about the Python-3000
mailing list