[Python-3000] Open Issues for string.format PEP

Ian Bicking ianb at colorstudy.com
Mon Apr 24 18:21:11 CEST 2006


Talin wrote:
>>>4) Should there be a way to pass in a dict argument without flattening it via
>>>**args?
>>
>>I think it might not be ambiguous in practice if the first argument 
>>could be a dictionary.  Because you get:
>>
>>   "{foo}".format(a_dict)
>>
>>Since 'foo' isn't an integer and *no* keyword arguments were passed, you 
>>assume a_dict is a dictionary.  Already "{0}" is going to look for 
>>positional arguments even if there is a dictionary with a '0' key, and I 
>>think that's just a reasonable limitation.  Then there's the case:
>>
>>   "{0} is {result}".format(a_dict)
>>
>>Is this an error?  I'm not sure; it doesn't really need to be, it'd just 
>>evaluate to "{'result': 5} is 5" or something.  Potentially this would 
>>be a problem, though:
>>
>>   "{0} is {result}".format(value, **vars)
>>
>>When vars was {}... statically it would be clear that you intended 
>>{result} to come from vars, but at runtime you couldn't detect that. 
>>But I can't really imagine where that would happen, especially if 
>>there's no support for KeyError.
> 
> 
> Waaaayy too much voodoo. I think that this kind of implicit deduction of "what
> the programmer meant" is what people are trying to avoid. (And, if you'll
> forgive me for saying so, it's rather Perl-ish.)

I don't think it's hard to tell in any specific circumstance what is 
happening; a programmer can statically determine what is happening 
easily given the actual method call and the template.

> I want to go back for a moment to the original question. Whenever someone asks
> me "how should we solve this problem?" the first thing I always ask is "do we
> really need to?" Once we've answered that, we can then go on to the issue of
> coming up with a solution.

Without this all dictionaries must be copied.  I think maybe Guido 
suggested something involving a shortcut that would not covert the 
dictionary, but that shortcut isn't available to Python so the behavior 
could be different for custom formatters implemented in Python.  Also, 
only dictionaries are allowed after **; that could be changed (maybe 
that's part of the signature changes?), but that doesn't change the fact 
that only a dictionary can be passed into a function with **.

In other words, avoiding a dictionary copy when using ** is something 
that requires terrible hacks and special cases, and *that* seems 
incredibly Perlish to me.

So there's some overhead.  That overhead could be considerable depending 
on the size of the namespace provided by the dictionary.  But it's fixed.

However, it pretty much ruins wrapping as a generalized strategy.  I 
noted a couple here: 
http://mail.python.org/pipermail/python-3000/2006-April/000358.html

Another wrapper could be a cascading dict:

   class CascadingDict(object):
       def __init__(self, *subdicts):
           self.subdicts = subdicts
       def __getitem__(self, key):
           for d in self.subdicts[:-1]:
               try:
                   return d[key]
               except KeyError:
                   pass
           return self.subdicts[-1][key]

So you could do ''.format(CascadingDict(locals(), globals())).  You 
could get a dictionary that doesn't require copying globals and locals, 
and instead delegates to a frame determined dynamically.  You could look 
keys up in a database.  You could look keys up in a translation 
database.  You could allow '.', like:

   class DottedDict(object):
       def __init__(self, d):
           self.d = d
       def __getitem__(self, item):
           parts = item.split('.')
           ob = self.d[parts[0]]
           for attr in parts[1:]:
               ob = getattr(ob, attr)
           return ob

There's lots and lots of ways of using this pattern.  Both % and 
string.Template allow for this pattern.  Python has been removing over 
time the need for namespaces to be plain dictionaries; adding another 
place where namespaces are constrained to plain dictionaries is a step 
backward.


-- 
Ian Bicking  /  ianb at colorstudy.com  /  http://blog.ianbicking.org


More information about the Python-3000 mailing list