sprintf behaviour

Carl Banks imbosol-1045931606 at aerojockey.com
Sat Feb 22 17:54:34 CET 2003


Bj?rn Lindberg wrote:
> In C, I can do the following to get positioned parameters to the *printf
> family of functions:
> 
> #include <stdio.h>
> 
> int main()
> {
>    char * a = "abc";
>    char * b = "def";
>    printf("-- %2$s -- %1$s --\n", a, b);
>    return 0;
> }
> 
> Unfortunately, this does not seem to work in Python:
> 
>>>> print "-- %2$s -- %1$s --" % ('a', 'b')
> Traceback (most recent call last):
>  File "<stdin>", line 1, in ?
> ValueError: unsupported format character '$' (0x24) at index 5
>>>> 
> 
> Why is this? Is it a bug or an oversight?

Neither.  The Python % operator does not try to be exactly equivalent
to printf formatting; there are differences between printf and % that
are intended and not overlooked.

Also, the 1$ thing in the printf is nonstandard.  I guess it works
with GCC, but I doubt it works with other C compilers.  Even if Python
did try to duplicate printf exactly, it wouldn't be a bug to leave out
a nonstandard feature.


> I'm running Python 2.3a1 on
> GNU/Linux. Is there some other way to achieve what I want?

Yes.  What you need to do is define a function such as byindex below;
this takes a tuple and turns it into a dict where the keys are the
stringized tuple indices:

    def byindex(t):
        n = len(t)
        r = map(str,xrange(n))
        return dict(zip(r,t))

Because the Python % operator can accept a dict, you can use this to
get the effect you seek, like this:

    >>> print "--- %(1)s --- %(0)s ---" % byindex(('a', 'b'))

Note that 1 and 2 in the GCC example are replaced with 0 and 1 here; I
did it that way because Python is strongly zero-based.  (I know C is
too; but Python is, I would say, much more strongly zero-based.)

If you must use 1 and 2 instead of 0 and 1, you can change xrange(n)
to xrange(1,n+1).


-- 
CARL BANKS




More information about the Python-list mailing list