String formatting with two dictionaries?
Robert Amesz
reqhye72zux at mailexpire.com
Tue Oct 9 19:44:23 EDT 2001
Xavier Defrang wrote:
>
> On Tue, 9 Oct 2001, Carsten Gaebler wrote:
>
>> "%(foo) %(bar)" % magic(dict1, dict2, ...)
>
> So what about writing a class called "magic" that takes a bunch of
> dictionaries as __init__ arguments, and use an overridden
> __getitem__ to perform look-ups thegiven dictionaries?
That was my first thought too. Shouldn't be hard to come up with
something useful:
- - -
class multidict:
def __init__(self, *dicts):
self.dicts = dicts
def __getitem__(self, item):
for dict in self.dicts:
try:
return dict[item]
except KeyError:
pass
raise KeyError(str(item))
d1 = {"foo": "bar"}
d2 = {"spam": "eggs"}
s = "%(foo)s %(spam)s"
print s % multidict(d1, d2)
- - -
Notice that this isn't a real dictionary: it only has a __getitem__
method. Conversely, it only *uses* that method, too. As such, its uses
are limited, but at a cost of only 12 lines of code that's hardly an
issue.
I once used an even simpler class to return a default value for a
dictionary, also for string interpolation. (Otherwise I'd have been
able to use dict.get(key, defaultvalue) directly, of course.)
What I'd like to see for the %(key)s type string interpolation is for
it to be slightly more forgiving in that the trailing 's' should be
optional (IMHO, of course). A % without any formatting character could
mean anything, but after %(key) there can hardly be any doubt that we
want something inserted at this point, and that 'something' is usually
a string. Even if it isn't a string, it will be coerced into one, and I
can't think of any case where this will display something other than
you'd expect[*]. (Thus, the 'principle of least suprise' is
maintained.)
I can't think of any code this would break. (It's hard to be certain:
the ability to catch exceptions could mean that some program actually
counts on this happening.)
Robert Amesz
--
[*] Testing a bit further, this isn't strictly true. Using %f will not
display as many digits as %s, when trying to display 1.0/7, and what's
even stranger is that the interactive display will show even more
digits. (A mantissa of 6, 12 and 17 digits, respectively.) It's a
curious, if minor inconsistency.
More information about the Python-list
mailing list