why 'double tuple' when using %s with print?

Steve Holden sholden at holdenweb.com
Fri Nov 10 10:54:31 EST 2000


jkndeja at my-deja.com wrote:
> 
> Hello Fredrik
> 
> Thanks for your reply. however, the fine manual also says:
> 
>  The %s conversion takes any Python object and converts it to a string
> using str() before formatting it
> 
This *might* be a documentation fault, at the very most.

Each % escape sequence in the format string (the left-hand operand of the
% operator) is replaced with the repr() of the corresponding element of
the tuple which is the right-hand operand of the % operator.  You can only
have a non-tuple on the right-hand side if either

    a)	There is only a single % escape in the formatting string, or

    b)	The right-hand side is a dictionary and you are using named
	escapes such as %(key)s

When the documentation says "the %s conversion takes *any* Python object..."
(my emphasis), you have to remember that this comes after a section saying
"The right argument should be a tuple with one item for each argument
required by the format string." (the section Fredrik quoted at you).

In other words, since the operator expects a tuple as its right-hand
operand (and offers you the alternative of a single object more
or less as a courtesy), when it *sees* a tuple, it expects a conversion
in the left-hand operand for each element in the tuple.

Consequently, if you wish to format a tuple as the single operand on the
right-hand side, you MUST put it in a tuple.  Think about how you would
handle formatting, say, a tuple and a string.  In that case you'd need
something like:

>>> "Tuple is %s, string is '%s'" % ((1,2,4,8), "Powers of two")
"Tuple is (1, 2, 4, 8), string is 'Powers of two'"

So, removing the string and just formatting the tuple, we need:

>>> "Tuple is %s" % ((1,2,4,8),)
'Tuple is (1, 2, 4, 8)'

When Python finds a tuple as the right-hand operand, it expects there will
be one conversion for each element of the tuple:

>>> "Tuple values are: %s %s %s %s" % (1,2,4,8)
'Tuple values are: 1 2 4 8'

It just isn't clever enough to "think" to itself "There's only one
formatting escape in the left-hand operand, so the user must want
me to show the whole tuple as a result":

>>> "Tuple is: (%s)" % (1,2,4,8)
Traceback (innermost last):
  File "<pyshell#2>", line 1, in ?
    "Tuple is: (%s)" % (1,2,4,8)
TypeError: not all arguments converted

It appears you want Python to be that clever.  In which case, you will
need to gather support and write a Python Enhancement Proposal.  Myself,
I'm happy living with the existing behavior, and I hope this has at least
helped you understand it, even if you still don't like it!

> Which is kind-of where I came in.
> 

Sorry to beat this to death.  Your misunderstanding is actually quite
reasonable.  I'm not necessarily arguing you are wrong, more trying to
put the run-time system's "point of view".

> I understand the other postings about repr() etc, but that wasn't my
> point. Isn't there an inconsistancy between the two sections in the
> manual, the one above, and the one you quote?
> 
Yes, but not a huge one.  Maybe Fred Drake would appreciate some help
in re-phrasing that section.  There's obviously some room for sensible
people to misunderstand!

> Also and FWIW ;-), what's the significance of the [*] footnote about a
> singleton? AFAIK this is a new use of the word, other than the OOP
> design pattern one, and I'm not clear about the meaning here.
> 
See 5.11, "Expression lists", in which it says:

"The trailing comma is required only to create a single tuple (a.k.a. a
singleton); it is optional in all other cases."

This is different from the *other* use of "singleton", which as far as I
can see applies to two of the nine uses of the term in the documentation!
In 7.1 and 7.1.2 the same term is used to describe None, a type which
has only a single instance.  I agree this is confusing: perhaps the other
seven occurrences should be replaced by "monople" or "uniple"?  Or maybe
you can think of a better term?

Hope this has at least cleared things up, if not necessarily to your
satisfaction.

regards
 Steve

>     Thanks
>     Jon N
> 
> In article <ZFAO5.4410$QH2.451702 at newsb.telia.net>,
>   "Fredrik Lundh" <fredrik at effbot.org> wrote:
> > jkndeja at my-deja.com wrote:
> > >     Here's a relatively simple question. If t is a tuple
> > >
> > > >>> t = (1,2)
> > >
> > > then I can print it with
> > >
> > > >>> print t
> > >
> > > to get the result. If I want to print is using the '%' operator,
> > > I try
> > >
> > > >>> print "my tuple is %s" % t
> > >
> > > but this gives me
> > >    TypeError: not all arguments converted
> >
> > the answer in the fine manual is equally simple:
> >
> >     http://www.python.org/doc/current/lib/typesseq-strings.html
> >
> >     "The right argument should be a tuple with one item for each
> >     argument required by the format string; if the string requires
> >     a single argument, the right argument may also be a single
> >     non-tuple object [*]
> >
> >     [*] A tuple object in this case should be a singleton.
> >
> > </F>
> >
> > <!-- (the eff-bot guide to) the standard python library:
> > http://www.pythonware.com/people/fredrik/librarybook.htm
> > -->
> >
> >
> 
> Sent via Deja.com http://www.deja.com/
> Before you buy.

-- 
Helping people meet their information needs with training and technology.
703 967 0887      sholden at bellatlantic.net      http://www.holdenweb.com/





More information about the Python-list mailing list