Python未在没有转换说明符的情况下对%引发异常

2024-05-16 06:19:12 发布

您现在位置:Python中文网/ 问答频道 /正文

字符串格式的%运算符描述为here。你知道吗

通常,当呈现一个没有转换说明符的字符串时,它会引发TypeError: not all arguments converted during string formatting。例如,"" % 1将失败。到目前为止,还不错。你知道吗

有时,如果%运算符右侧的参数是空的,它不会失败:"" % [],或"" % {}"" % ()将静默地返回空字符串,看起来很公平。你知道吗

"%s"代替空字符串也会将空对象转换成字符串,但最后一个会失败,但我认为这是%运算符问题的一个实例,它是通过format方法解决的。你知道吗

还有一个非空字典的例子,比如"" % {"a": 1},它之所以有效是因为它实际上应该与命名类型说明符一起使用,比如"%(a)d" % {"a": 1}。你知道吗

但是,有一种情况我不明白:"" % b"x"将返回空字符串,没有引发异常。为什么?你知道吗


Tags: 字符串参数stringhere公平格式not运算符
2条回答

我不是百分之百确定,但是在快速查看sources之后,我想原因如下:

%右边只有一个参数时,Python会检查它是否有getitem方法,如果有,则假定它是一个映射,并希望我们使用像%(name)s这样的命名格式。否则,Python将从参数创建一个元素元组,并执行位置格式化。参数计数不使用映射检查,因此,由于byteslists确实有getitem,它们不会失败:

>>> "xxx" % b'a'
'xxx'
>>> "xxx" % ['a']
'xxx'

同时考虑:

>>> 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'

字符串是此规则的例外-它们有getitem,但对于位置格式仍然是“元组化的”:

>>> "xxx" % 'a'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: not all arguments converted during string formatting

当然,这种“序列作为映射”的逻辑意义不大,因为格式化键总是字符串:

>>> "xxx %(0)s" % ['a']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: list indices must be integers, not str

但我怀疑是否有人能解决这个问题,因为%无论如何都被抛弃了。你知道吗

有问题的行位于unicodeobject.c。它认为所有对象都是“映射”,并且显式地不是元组或字符串,或者它们的子类,都是“字典”,对于那些对象,如果不是所有的参数都被转换,它就不是错误的。你知道吗

^{}定义为:

int
PyMapping_Check(PyObject *o)
{
    return o && o->ob_type->tp_as_mapping &&
        o->ob_type->tp_as_mapping->mp_subscript;
}

也就是说,任何定义了tp_as_mapping且具有mp_subscript的类型都是映射。你知道吗

bytesdefine that,就像其他任何有__getitem__的对象一样。因此,至少在python3.4中,__getitem__的对象不会作为%格式op的右侧参数失败

现在这是对Python2.7的修改。此外,这样做的原因是没有办法检测所有可能用于%(name)s格式化的类型,除非接受所有实现__getitem__的类型,尽管已经排除了最明显的错误。当python3发布时,没有人在那里添加bytes,尽管它显然不应该支持字符串作为__getitem__的参数;但是那里也没有list。你知道吗

另一个疏忽是列表不能用于设置位置参数的格式。你知道吗

相关问题 更多 >