string formatting with mapping & '*'... is this a bug?

Pierre Fortin pfortin at
Fri Sep 10 12:46:59 CEST 2004

On Fri, 10 Sep 2004 08:27:44 +0200 Alex wrote:

> Pierre Fortin <pfortin at> wrote:
>    ...
> > I was hoping to use the likes of:  "%(key)*.*f" % map
> > however, unlike with the non-(key) formats, there appears to be no way
> > to specify a "*.*" size when a map is used...
> It is not clear to me where you would expect to get the values for those
> stars from -- 'map' being a dictionary it has no concept of "ordering",
> so there is no concept of "next value" after map['key'].  If I had this
> kind of problem I would doubtlessly tack it with _two_ formattings,
> first one to get the values for the stars (with explicit names), giving
> a clean format string, then another to get the value for the data.  Say:
> '%%(key)%(width)d.%(prec)df' % map % map
> Not all that readable, alas.  Alternatively, you could use a non-keyed
> format string and extract things from the map on the RHS...:
> '%*.*f' % [map[x] for x in ('key', 'width', 'prec')]
> I personally consider this a bit more readable, but that's quite
> debatable, of course...
> Alex

Thanks to you and Bengt for your patience with this problem...

Since I'd already dipped my toe in the dual-map water in an earlier post,
a "Duh!" moment occured to me as I read your responses...  Realizing that
examples rarely show the true complexity of a problem, the answer (for me)
lay in keeping the formatting and data maps separate...  I find mapped
strings immensely more readable/maintainable than the simple same-quantity
and gotta-be-in-the-right-order ones:

   """On %10s, the closing price of $%6.2f was %s
   from the day's open of $%6.2f 
   """ % (Date, Close, change[int(float(Open>= ...], Open, ... )

especially when the string needs to be reworked by re-ordering, adding
and/or deleting items.

Here's my reasonably (to me :) readable/maintainable solution to this core
problem...  Only the "fmt" statement needs tweaking to generate the
desired appearance.

#!/usr/bin/env python

def mkdict(**kwargs):
    return kwargs

fmt = { 'wDate':10, 'wOpen':6, 'wHigh':6, 'wLow':6,  # width
        'wClose':6, 'wVolume':10, 'wAdjClose':6,
        'pDate':10, 'pOpen':2, 'pHigh':2, 'pLow':2,  # precision
        'pClose':2, 'pVolume':0, 'pAdjClose':2 }

# data will be read from several thousand files
sampledata = [


for D in sampledata:
    Date, Open, High, Low, Close, Volume, AdjClose = D.split(',')

    map = mkdict(Date=Date,
                 Change=change[int(float(AdjClose) >= float(Open)) +
                               int(float(AdjClose) == float(Open))]
    # line continuations must be left-justified to avoid extra spaces
    print "%%(Date)%(wDate)d.%(pDate)ds \
%%(Open)%(wOpen)d.%(pOpen)df \
%%(High)%(wHigh)d.%(pHigh)df \
%%(Low)%(wLow)d.%(pLow)df \
%%(Close)%(wClose)d.%(pClose)df \
%%(Volume)%(wVolume)d.%(pVolume)dd \
%%(AdjClose)%(wAdjClose)d.%(pAdjClose)df \
%%(Change)s \
" % fmt % map

  9-Sep-04  19.49  20.03  19.35  19.93   60077400  19.93 up
  8-Sep-04  18.96  19.53  18.92  18.97   52020600  18.96 n/c
  7-Sep-04  18.98  19.18  18.84  18.85   45498100  18.84 down

At least, now I understand why mappings are the exception to the "*[.*]"
rule of formatting... :^)


More information about the Python-list mailing list