>>> \'string with no string formatting markers\' % [\'string\']
\'string with no string formatting markers\'
>>> \'string with no string formatting
Reading carefully, the documentation states that:
If format requires a single argument, values may be a single non-
tuple
object. Otherwise, values must be atuple
with exactly the number of items specified by the format string, or a single mapping object (for example, a dictionary).
Now, in this case the format
does not require a single argument and thus the documentation tells us that you should use a tuple
or a mapping as argument; other cases fall in "undefined behaviour"(which is what is happening: the behaviour is not consistent in all cases).
This should probably be considered the final answer to the question: if the string does not have any format specifier, using a list
(or any kind different from tuple
or a mapping) should simply be considered a bug by itself leading to undefined behaviour.
From this follows that you ought to always use a tuple
or dict
as argument, otherwise you have to check for format specifiers by hand or handle odd behaviours.
In your case you can probably fix the problem using (['string'], )
instead of ['string']
.
Possible "explanation" of why the resultant behaviour seems to be so random:
It seems like there was a buggy check in the original implementation of PyString_Format
/PyUnicode_Format
, instead of using PyMappingCheck
on this line:
if (PyMapping_Check(args) && !PyTuple_Check(args) &&
!PyObject_TypeCheck(args, &PyBaseString_Type))
dict = args;
It was used this code:
if (Py_TYPE(args)->tp_as_mapping && !PyTuple_Check(args) &&
!PyObject_TypeCheck(args, &PyBaseString_Type))
dict = args;
which is not equivalent. For example set
does not have tp_as_mapping
set(at least in the Python2.7.3 source code that I have downloaded some weeks ago), while list
does set it.
This might be the reason why list
(and possibly other objects) do not raise the TypeError
while, set
, int
and many others do.
As I stated before in this same answer I do get TypeError
even with list
s:
$ python2
Python 2.7.3 (default, Sep 26 2012, 21:53:58)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 'some string' % []
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: not all arguments converted during string formatting
This probably shows that the above issue is not the only one here.
Looking at the source code I agree that, in theory, the number of arguments is not checked if the argument is not a tuple, but this would imply 'some string' % 5 -> 'some string'
and not a TypeError
, so there must be something fishy in that code.