<p>我不是百分之百确定,但是在快速查看<a href="https://github.com/python/cpython/blob/master/Objects/unicodeobject.c" rel="nofollow">sources</a>之后,我想原因如下:</p>
<p>当<code>%</code>右边只有一个参数时,Python会检查它是否有<code>getitem</code>方法,如果有,则假定它是一个映射,并希望我们使用像<code>%(name)s</code>这样的命名格式。否则,Python将从参数创建一个元素元组,并执行位置格式化。参数计数不使用映射检查,因此,由于<code>bytes</code>和<code>lists</code>确实有<code>getitem</code>,它们不会失败:</p>
<pre><code>>>> "xxx" % b'a'
'xxx'
>>> "xxx" % ['a']
'xxx'
</code></pre>
<p>同时考虑:</p>
<pre><code>>>> class X: pass
...
>>> "xxx" % X()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: not all arguments converted during string formatting
>>> class X:
... def __getitem__(self,x): pass
...
>>> "xxx" % X()
'xxx'
</code></pre>
<p>字符串是此规则的例外-它们有<code>getitem</code>,但对于位置格式仍然是“元组化的”:</p>
<pre><code>>>> "xxx" % 'a'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: not all arguments converted during string formatting
</code></pre>
<p>当然,这种“序列作为映射”的逻辑意义不大,因为格式化键总是字符串:</p>
<pre><code>>>> "xxx %(0)s" % ['a']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: list indices must be integers, not str
</code></pre>
<p>但我怀疑是否有人能解决这个问题,因为<code>%</code>无论如何都被抛弃了。你知道吗</p>