[Python-Dev] Binary Operator for New-Style String Formatting

Terry Reedy tjreedy at udel.edu
Sun Jun 21 21:12:16 CEST 2009

Jerry Chen wrote:
> Hello all,
> For better or for worse, I have created a patch against the py3k trunk
> which introduces a binary operator '@' as an alternative syntax for
> the new string formatting system introduced by PEP 3101 ("Advanced
> String Formatting"). [1]
> For common cases, this syntax should be as simple and as elegant as
> its deprecated [2] predecessor ('%'), while also ensuring that more
> complex use cases do not suffer needlessly.
> I would just like to know whether this idea will float before

The place to float trial balloons is the python-ideas list.

> submitting the patch on Roundup and going through the formal PEP
> process.  This is my first foray into the internals of the Python

Even if this particular idea in not accepted, I hope you learned from 
and enjoyed the exercise and will try other forays.

> core, and with any luck, I did not overlook any BDFL proclamations
> banning all new binary operators for string formatting. :-)
>     >>> "{} {} {}" @ (1, 2, 3)

The only advantage '@' over '.format' is fewer characters.
I think it would be more useful to agitate to give 'format' a one char 
synonym such as 'f'.

One disadvantage of using an actual tuple rather than an arg quasi-tuple 
is that people would have to remember the trailing comma when printing 
one thing. '{}' @ (1,) rather than '{}' @ (a) == '{}' @ a. [If you say, 
'Oh, then accept the latter', then there is a problem when a is a tuple!]

>     '1 2 3'
>     >>> "foo {qux} baz" @ {"qux": "bar"}
>     'foo bar baz'
> One of the main complaints of a binary operator in PEP 3101 was the
> inability to mix named and unnamed arguments:
>     The current practice is to use either a dictionary or a tuple as
>     the second argument, but as many people have commented ... this
>     lacks flexibility.
> To address this, a convention of having the last element of a tuple
> as the named arguments dictionary is introduced.
>     >>> "{} {qux} {}" @ (1, 3, {"qux": "bar"})
>     '1 bar 3'
> Lastly, to print the repr() of a dictionary as an unnamed argument,
> one would have to append an additional dictionary so there is no
> ambiguity:
>     >>> "{}" @ {"foo": "bar"}
>     Traceback (most recent call last):
>       File "<stdin>", line 1, in <module>
>     IndexError: tuple index out of range
>     >>> "{}" @ ({"foo": "bar"}, {})
>     "{'foo': 'bar'}"

This is another disadvantage -- to me a big one.

Formatting is inherently an n-ary function who args are one format and 
an indefinite number of objects to plug in. Packaging the remaining args 
into an object to convert the function to binary is problematical, 
especially in Python with its mix of positional and named args. Even 
without that, there is possible confusion between a package as an arg in 
itself and a package as a container of multiple args. The % formatting 
problem with tuple puns was one of the reasons to seek a replacement.

Terry Jan Reedy

> Admittedly, these workarounds are less than clean, but the
> understanding is the '@' syntax would indeed be an alternative, so one
> could easily fall back to the str.format() method or the format()
> function.
> Code-wise, the grammar was edited per PEP 306 [3], and a
> function was introduced in unicodeobject.c as PyUnicode_FormatPrime
> (in the mathematical sense of A and A' -- I didn't fully understand or
> want to intrude upon the *_FormatAdvanced namespace).
> The PyUnicode_FormatPrime function transforms the incoming arguments,
> i.e. the operands of the binary '@', and makes the appropriate
> do_string_format() call.  Thus, I have reused as much code as
> possible.
> I have done my development with git by using two branches: 'master'
> and 'subversion', the latter of which can be used to run 'svn update'
> and merge back into master.  This way my code changes and the official
> ones going into the Subversion repository can stay separate, meanwhile
> allowing 'svn diff' to produce an accurate patch at any given time.
> The code is available at:
>     http://github.com/jcsalterego/py3k-atsign/
> The SVN patch [4] or related commit [5] are good starting points.
> References:
> [1] http://www.python.org/dev/peps/pep-3101
> [2] http://docs.python.org/3.0/whatsnew/3.0.html
> [3] http://www.python.org/dev/peps/pep-0306/
> [4] http://github.com/jcsalterego/py3k-atsign/blob/master/py3k-atsign.diff
> [5] http://github.com/jcsalterego/py3k-atsign/commit/5c8bdf72d9252cea78af2b7809613f6530e25db4
> Thanks,

More information about the Python-Dev mailing list