Ответ 1
Отличный вопрос! Я верю, что у меня есть ответ. Это требует копания через исходный код Python на C, так что несите меня.
Во-первых, format(obj, format_spec)
является просто синтаксическим сахаром для obj.__format__(format_spec)
. Для конкретного случая, когда это происходит, вам нужно искать abstract.c в функции:
PyObject *
PyObject_Format(PyObject* obj, PyObject *format_spec)
{
PyObject *empty = NULL;
PyObject *result = NULL;
...
if (PyInstance_Check(obj)) {
/* We're an instance of a classic class */
HERE -> PyObject *bound_method = PyObject_GetAttrString(obj, "__format__");
if (bound_method != NULL) {
result = PyObject_CallFunctionObjArgs(bound_method,
format_spec,
NULL);
...
}
Чтобы найти точный вызов, мы должны посмотреть intobject.c:
static PyObject *
int__format__(PyObject *self, PyObject *args)
{
PyObject *format_spec;
...
return _PyInt_FormatAdvanced(self,
^ PyBytes_AS_STRING(format_spec),
| PyBytes_GET_SIZE(format_spec));
LET FIND THIS
...
}
_PyInt_FormatAdvanced
фактически определяется как макрос в formatter_string.c как функция, найденная в formatter.h:
static PyObject*
format_int_or_long(PyObject* obj,
STRINGLIB_CHAR *format_spec,
Py_ssize_t format_spec_len,
IntOrLongToString tostring)
{
PyObject *result = NULL;
PyObject *tmp = NULL;
InternalFormatSpec format;
/* check for the special case of zero length format spec, make
it equivalent to str(obj) */
if (format_spec_len == 0) {
result = STRINGLIB_TOSTR(obj); <- EXPLICIT CAST ALERT!
goto done;
}
... // Otherwise, format the object as if it were an integer
}
И в этом ваш ответ. Простая проверка того, является ли format_spec_len
0
, а если это так, преобразуйте obj
в строку. Как вы хорошо знаете, str(True)
есть 'True'
, и тайна закончилась!