string formatting with mapping & '*'... is this a bug?
Pierre Fortin
pfortin at pfortin.com
Fri Sep 10 06:46:59 EDT 2004
On Fri, 10 Sep 2004 08:27:44 +0200 Alex wrote:
> Pierre Fortin <pfortin at pfortin.com> 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:
change=["down","up","unchanged"]
"""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 = [
"9-Sep-04,19.49,20.03,19.35,19.93,60077400,19.93",
"8-Sep-04,18.96,19.53,18.92,18.97,52020600,18.96",
"7-Sep-04,18.98,19.18,18.84,18.85,45498100,18.84",
]
change=["down","up","n/c"]
for D in sampledata:
Date, Open, High, Low, Close, Volume, AdjClose = D.split(',')
map = mkdict(Date=Date,
Open=float(Open),
High=float(High),
Low=float(Low),
Close=float(Close),
Volume=int(Volume),
AdjClose=float(AdjClose),
#
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
Generates:
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... :^)
Thanks!
Pierre
More information about the Python-list
mailing list