[Python-Dev] PEP 3101: Advanced String Formatting (original) (raw)

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