Python does not throw% exception without conversion specifier

The% operator for formatting strings is described here .

Usually, when a string is presented without a conversion specifier, it will raise the value TypeError: not all arguments converted during string formatting. For example, it "" % 1will fail. So far so good.

Sometimes this will not fail if the argument to the right of the% operator is something empty: "" % []or "" % {}or it "" % ()will silently return an empty string, and it looks fairly honestly.

The same with "%s"converting an empty object to a string instead of an empty string, with the exception of the latter, which will fail, but I think this is an instance of the% operator problems that can be solved with format.

There is also a case of a non-empty dictionary, for example "" % {"a": 1}, that works because it really should be used with named type specifiers, for example, in "%(a)d" % {"a": 1}.

However, there is one case that I do not understand: it "" % b"x"will return an empty string, an exception will not be thrown. Why?

+4
source share
2 answers

I'm not 100% sure, but after a quick look at the sources, I think the reason is this:

%, Python , getitem, , , , , , %(name)s. Python . , , bytes lists 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, - "tuplified" :

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

, - , , % .

+2

unicodeobject.c. , "", , , , "", , , .

PyMapping_Check :

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

bytes , __getitem__. , Python 3.4, , __getitem__ % op.

Python 2.7. , , , %(name)s, , , __getitem__, , Python 3 , bytes, __getitem__; list.

, .

+2

All Articles