patternpythonMinor
Right-justifying a number with dot leaders
Viewed 0 times
numberwithdotjustifyingleadersright
Problem
I'm working on a small library to help me format numbers easier as my current project deals with a lot of them. I want to be able to just supply the value, precision, width, and fillchar to a method and have it do all the work for me.
Based on the standard way of doing things with
… I could write:
However, I have found that the
… so I could also write it this way:
My main question is, should I used the
Based on the standard way of doing things with
rjust()…print '{:.2f}'.format(123.456).rjust(10, '.')
# ....123.46… I could write:
def float_rjust(value, width, precision=2, fillchar=' ', separator='', sign=''):
#[sign][#][0][width][,][.precision][type]
spec = '{{:{1}{2}{3}.{4}f}}'.format(
sign,
width,
separator,
precision
)
return spec.format(value).rjust(width, fillchar)However, I have found that the
format() method actually allows for justifications in it:print '{:.>10.2f}'.format(123.456)
# ....123.46… so I could also write it this way:
def float_rjust(value, width, precision=2, fillchar=' ', separator='', sign=''):
#[[fill]align][sign][#][0][width][,][.precision][type]
spec = '{{:{0}>{1}{2}{3}.{4}f}}'.format(
fillchar,
sign,
width,
separator,
precision
)
return spec.format(value)My main question is, should I used the
[[fill]align] formatting spec in format() to do justification, or is it more Pythonic to use format().rjust()?Solution
In terms of efficiency, the second form is probably slightly better, as it creates fewer string objects:
vs.
In general terms, I would use e.g.
However, I would probably rearrange this completely. You have combined two steps that I think should probably be separate: creating a specification, and applying it to an object.
Using
You can now inline the
For greater efficiency, as
def float_rjust(value, width, precision=2, fillchar=' ', separator='', sign=''):
#[sign][#][0][width][,][.precision][type]
spec = '{{:{1}{2}{3}.{4}f}}'.format( # 1
sign,
width,
separator,
precision
) # 2
value = spec.format(value) # 3 - slight refactor for clarity
return value.rjust(width, fillchar) # 4vs.
def float_rjust(value, width, precision=2, fillchar=' ', separator='', sign=''):
#[[fill]align][sign][#][0][width][,][.precision][type]
spec = '{{:{0}>{1}{2}{3}.{4}f}}'.format( # 1
fillchar,
sign,
width,
separator,
precision
) # 2
return spec.format(value) # 3In general terms, I would use e.g.
rjust only where that was the only formatting I required; it seems awkward to split the formatting into two steps.However, I would probably rearrange this completely. You have combined two steps that I think should probably be separate: creating a specification, and applying it to an object.
Using
format(value, spec) rather than spec.format(value) (i.e. the format function vs. the str.format method) lets you simplify the spec (getting rid of the extra braces):def float_spec(width, precision=2, fillchar=' ', separator='', sign=''):
"""Create a specification for formatting floats."""
return '{}>{}{}{}.{}f'.format(fillchar, sign, width, separator, precision)You can now inline the
format call:>>> print format(123.456, float_spec(width=10, fillchar='.'))
....123.46For greater efficiency, as
float_spec would return equal (but not identical) strings for the same inputs, you could add memoization/caching. You could also add validation (of either the parameters or created specs) to ensure that it outputs a valid specification for format.Code Snippets
def float_rjust(value, width, precision=2, fillchar=' ', separator='', sign=''):
#[sign][#][0][width][,][.precision][type]
spec = '{{:{1}{2}{3}.{4}f}}'.format( # 1
sign,
width,
separator,
precision
) # 2
value = spec.format(value) # 3 - slight refactor for clarity
return value.rjust(width, fillchar) # 4def float_rjust(value, width, precision=2, fillchar=' ', separator='', sign=''):
#[[fill]align][sign][#][0][width][,][.precision][type]
spec = '{{:{0}>{1}{2}{3}.{4}f}}'.format( # 1
fillchar,
sign,
width,
separator,
precision
) # 2
return spec.format(value) # 3def float_spec(width, precision=2, fillchar=' ', separator='', sign=''):
"""Create a specification for formatting floats."""
return '{}>{}{}{}.{}f'.format(fillchar, sign, width, separator, precision)>>> print format(123.456, float_spec(width=10, fillchar='.'))
....123.46Context
StackExchange Code Review Q#93190, answer score: 4
Revisions (0)
No revisions yet.