custom formatter in python 3
Formatting has changed (for the better) in python 3. It’s still something I’m training myself to use (years of habitually using %s has to be relearned)
One useful new feature is writing custom formatting functions: so just as real number can be rendered as a using the built-in rounded number formatter, so other formatting can be crafted — see the code for an uppercase & lowercase formatter:
from string import Formatter
class ExtendedFormatter(Formatter):
"""
>>>myformatter = ExtendedFormatter()
>>>output = myformatter.format("normal:{test}, upcase:{test!u},
lowcase:{test!l}", test="DiDaDoDu")
>>>print(output)
normal:DiDaDoDu, upcase:DIDADODU, lowcase:didadodu All default formatting still supported
>>>myformatter.format("UKP {:.1f}", 444.44543)
>>>print(output)
UKP 444.4
"""
def convert_field(self, value, conversion):
""" Extend conversion symbol
Following additional symbol has been added
* l: convert to string and lowercase
* u: convert to string and uppercase
"""
RECOGNIZED_FORMATTERS = {
'u': lambda value: str(value).upper(),
'l': lambda value: str(value).lower(),
}
try:
return RECOGNIZED_FORMATTERS[conversion](value)
except KeyError:
# Do the default conversion
return super(ExtendedFormatter,self).convert_field(
value, conversion)
A few notes on the Python
No case construct
Python doesn’t have an explicit ‘case’ statement. The reason given is that it’s easy enough to simulate one with a dict, as shown above.
Ask for forgiveness, not permission
Note the EAFP pattern: if the format requested isn’t in the custom lookup, catch this exception and handle it with the default formatter. We’re also making use of CAPITALS being the convention for a constant. There’s also a couple of doctests: Used for both documenting and testing of the function.
Anonymous functions
The formatting functions shown (converting to upper/lower case) are trivial, so the functions are written out as ‘anonymous’ functional style: they’re not defined and named as usual — just the guts of the function are written out ‘in-line’. This is just a matter of style/preference/clarity and is entirely equivalent to writing out as :
def upper(value):
return str(value).upper()
As the function is simple, and will never be reused in any other context, this is a good example of a lambda in Python.
Thanks to this stack overflow discussion for insights.