为什么使用列表作为字符串格式参数,即使没有%s标识符,也会返回原始字符串?

Fre*_*nan 12 python string-formatting

>>> 'string with no string formatting markers' % ['string']
'string with no string formatting markers'
>>> 'string with no string formatting markers' % ('string',)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: not all arguments converted during string formatting
Run Code Online (Sandbox Code Playgroud)

我希望两种情况都能提高TypeError,但事实并非如此.为什么不?

关于这个主题的Python文档讨论了字符串,元组和字典,但没有说明列表.我对这种行为有点困惑.我已经能够在Python 2.7和3.2中复制它.

Bak*_*riu 6

仔细阅读,文档说明:

如果format需要单个参数,则值可以是单个非tuple 对象.否则,值必须tuple与格式字符串指定的项目数或单个映射对象(例如,字典)完全相同.

现在,在这种情况下,format不需要单个参数,因此文档告诉我们您应该使用a tuple或映射作为参数; 其他情况属于"未定义的行为"(正在发生的事情:行为在所有情况下都不一致).

这可能应该被认为是问题的最终答案:如果字符串没有任何格式说明符,使用list(或任何不同的tuple或映射的类型)应该只被视为一个错误本身导致未定义的行为.

由此可见,您应始终使用tupledict作为参数,否则您必须手动检查格式说明符或处理奇怪的行为.

在您的情况下,您可以使用(['string'], )而不是使用来修复问题['string'].


可能的"解释"为什么结果行为似乎是如此随机:

似乎在/ 的原始实现中有一个错误的检查,而不是在这一行上使用:PyString_FormatPyUnicode_FormatPyMappingCheck

if (PyMapping_Check(args) && !PyTuple_Check(args) &&
     !PyObject_TypeCheck(args, &PyBaseString_Type))
    dict = args;
Run Code Online (Sandbox Code Playgroud)

它使用了这段代码:

if (Py_TYPE(args)->tp_as_mapping && !PyTuple_Check(args) &&
    !PyObject_TypeCheck(args, &PyBaseString_Type))
    dict = args;
Run Code Online (Sandbox Code Playgroud)

这不等同.例如set,没有tp_as_mapping设置(至少在几周前我已经下载的Python2.7.3源代码中),同时list确实设置了它.

这可能是为什么的原因list(可能还有其他对象)不提高的TypeError同时,set,int和许多其他事情.

正如我之前在同一个答案中所说,我甚至得到TypeErrorlists:

$ 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
Run Code Online (Sandbox Code Playgroud)

这可能表明上述问题不是唯一的问题.

查看源代码我同意理论上,如果参数不是元组,则不检查参数的数量,但这意味着'some string' % 5 -> 'some string'而不是a TypeError,因此在该代码中必定存在一些可疑的东西.

  • 您正在尝试使用什么版本的python 2?我无法在2.5.4,2.6.1或2.7.2上重现这一点 (2认同)