Возвращение int из метода __str__ в Python - PullRequest
0 голосов
/ 11 сентября 2018

Я знаю, что цель метода str() - вернуть строковое представление объекта, поэтому я хотел проверить, что произойдет, если я заставлю его сделать что-то еще.

Я создал класс и объект:

class MyClass(object):

    def __str__(self, a=2, b=3):
        return a + b

mc = MyClass()

Когда я звоню:

print(str(mc))

Переводчик жалуется:

TypeError: __str__ returned non-string (type int)

И это вполне понятно, потому что метод str () пытается вернуть int .

Но если я попытаюсь:

print(mc.__str__())

Я получаю вывод: 5.

Так почему интерпретатор позволяет мне возвращать int, когда я вызываю __str__ напрямую, а не когда я использую str (mc), которая - как я понимаю - также оценивается как mc.__str__().

Ответы [ 5 ]

0 голосов
/ 11 сентября 2018

str это не просто

def str(obj):
    return obj.__str__()

Я думаю, что очень немногие из стандартных функций или операторов отображают напрямую на подобный магический метод, хотя я не уверен в точных значениях.

str пытается __str__, но также пытается __repr__, если нет __str__, и применяет тип возврата str. (Он также вызывает возвращаемое значение __init__ по техническим причинам , что может показаться странным для str подклассов .) + пытается __add__, но также пытается __radd__. iter пытается __iter__, но также пытается __getitem__. Список можно продолжать и продолжать.

0 голосов
/ 11 сентября 2018

Встроенная функция str (а также repr) делает больше, чем просто вызов .__str__ (или .__repr__) - они также имеют значения по умолчанию для работы с объектами, которые не имеют __str__или __repr__ метод, и некоторая сообразительность для работы с объектами, чье строковое представление является рекурсивным.

Вы можете увидеть источник (в C) для str и repr здесь и здесь .Как вы можете видеть, они принудительно возвращают тип возврата __str__ и __repr__:

if (!PyUnicode_Check(res)) {
    PyErr_Format(PyExc_TypeError,
                 "__str__ returned non-string (type %.200s)",
                 Py_TYPE(res)->tp_name);
    Py_DECREF(res);
    return NULL;
}

Если вы просто вызываете метод __str__ для объекта, Python сам не применяет этот методвызываемый __str__ может возвращать только строку - это функция str, которая применяет это ограничение.

0 голосов
/ 11 сентября 2018

__ str __ используется аналогично методу ToString в Java, где вы получите дружественную печать объекта класса.

0 голосов
/ 11 сентября 2018

str() звонки PyObject_Str(). Здесь - исходный код, в котором определено PyObject_Str(). Если вы ищете в этом документе «__str__», вы увидите, где функция вызывает __str__, и убедитесь, что тип возвращаемого значения на самом деле является строкой.

0 голосов
/ 11 сентября 2018

__str__ предоставляет контракт: вы возвращаете строку, и программа не прерывается, когда она пытается использовать нестроковое значение, когда программа ожидает строку. Определение того, действительно ли __str__ подчиняется , этот контракт вообще не вычисляется, поэтому программист должен исполнить контракт.

Как указывает @ Juanpa.arrivillaga, str просто строже в методе __str__, возвращающем, каким он должен быть. Ваш явный вызов __str__ фактически не вызывает протокол; он возвращает значение int, но само это значение имеет метод __str__, который print вызывает, когда ему требуется значение str.

...