[Python-Dev] PEP 3101: Advanced String Formatting

Talin talin at acm.org
Sun Apr 30 22:33:54 CEST 2006


Zachary Pincus wrote:
> I'm not sure about introducing a special syntax for accessing 
> dictionary entries, array elements and/or object attributes *within a 
> string formatter*... much less an overloaded one that differs from how 
> these elements are accessed in "regular python".
>>> Compound names are a sequence of simple names seperated by
>> periods:
>>>> "My name is {0.name} :-\{\}".format(dict(name='Fred'))
>>>> Compound names can be used to access specific dictionary entries,
>> array elements, or object attributes. In the above example, the
>> '{0.name}' field refers to the dictionary entry 'name' within
>> positional argument 0.
>>> Barring ambiguity about whether .name would mean the "name" attribute 
> or the "name" dictionary entry if both were defined, I'm not sure I 
> really see the point. How is:
> d = {last:'foo', first:'bar'}
> "My last name is {0.last}, my first name is {0.first}.".format(d)
>> really that big a win over:
> d = {last:'foo', first:'bar'}
> "My last name is {0}, my first name is {1}.".format(d['last'], d 
> ['first'])

At one point I had intended to abandon the compound-name syntax, until I 
realized that it had one beneficial side-effect, which is that it offers 
a way around the 'dict-copying' problem.
There are a lot of cases where you want to pass an entire dict as the 
format args using the **kwargs syntax. One common use pattern is for 
debugging code, where you want to print out a bunch of variables that 
are in the local scope:
 print "Source file: {file}, line: {line}, column: {col}"\
 .format( **locals() )
The problem with this is one of efficiency - the interpreter handles **
by copying the entire dictionary and merging it with any keyword arguments.
Under most sitations this is fine; However if the dictionary is 
particularly large, it might be a problem. So the intent of the
compound name syntax is to allow something very similar:
 print "Source file: {0.file}, line: {0.line}, column: {0.col}"\
 .format( locals() )
Now, its true that you could also do this by passing in the 3 parameters 
as individual arguments; However, there have been some strong proponents 
of being able to pass in a single dict, and rather than restating their 
points I'll let them argue their own positions (so as not to 
accidentally mis-state them.)
> Plus, the in-string syntax is limited -- e.g. what if I want to call a 
> function on an attribute? Unless you want to re-implement all python 
> syntax within the formatters, someone will always be able to level 
> these sort of complaints. Better, IMO, to provide none of that than a 
> restricted subset of the language -- especially if the syntax looks and 
> works differently from real python.

The in-string syntax is limited deliberately for security reasons. 
Allowing arbitrary executable code within a string is supported by a 
number of other scripting languages, and we've seen a good number of 
exploits as a result.
I chose to support only __getitem__ and __getattr__ because I felt that 
they would be relatively safe; usually (but not always) those functions 
are written in a way that has no side effects.
-- Talin


More information about the Python-Dev mailing list

AltStyle によって変換されたページ (->オリジナル) /