如果 t.__str__() 返回非字符串,为什么 print(t) 错误,而不是 print(t.__str__()) ?

Man*_*hna 30 python type-conversion typeerror magic-methods

我试图理解__str__Python 中的方法。

class Test:
    def __str__(self):
        return 5

t = Test()

print(t.__str__())
Run Code Online (Sandbox Code Playgroud)

在此方法中,它返回一个整数值,但打印方法能够打印它。

但是,当我尝试时,print(t)它抛出了错误 TypeError: __str__ returned non-string (type int)

据我了解print(t),也在调用该__str__(self)方法。

为什么不print(t.__str__())想要字符串类型转换?

dec*_*eze 30

你在做什么等价于print(5),它的工作原理是print调用__str__5得到一个字符串。但是传递对象,print调用__str__该对象并没有得到实际的字符串作为响应。


Sor*_*ary 24

这都是关于 python 对一些内置函数进行的额外检查。

len() --> __len__() + some checks
str() --> __str__() + some checks
Run Code Online (Sandbox Code Playgroud)

“您”显式调用方法或“Python”调用该方法时是有区别的!关键是当 Python 调用你的方法时,它会为你做一些检查。(这是我们应该使用那些内置函数而不是调用相关的 dunder 方法的原因之一。)

我们也可以通过len()和看到这种行为__len__()

class Test:
    def __len__(self):
        return 'foo'

t = Test()

print(t.__len__())  # fine
print(len(t))       # TypeError: 'str' object cannot be interpreted as an integer
Run Code Online (Sandbox Code Playgroud)

所以python检查在第二个打印语句中返回整数!这就是__len__().

同样的事情发生在这里。当您调用print(t) Python 本身调用 __str__()方法时,它检查是否__str__()返回预期的字符串。(同样的事情发生在str(t)

但是,当你说print(t.__str__()),首先,你__str__()自己在实例上显式调用它的方法时,这里没有检查......返回什么?number 5,然后 python 将运行print(5)


Ale*_*lex 8

当您t.__str__()直接调用时,它就像任何其他方法一样。方法 __str__方法被覆盖了,所以直接调用的时候没什么特别的。

做的时候 print(t)内部调用时,会进行一些类型检查

if (!PyUnicode_Check(res)) {
    _PyErr_Format(tstate, PyExc_TypeError,
                  "__str__ returned non-string (type %.200s)",
                  Py_TYPE(res)->tp_name);
    Py_DECREF(res);
    return NULL; 
Run Code Online (Sandbox Code Playgroud)

手册指出:

返回值必须是字符串对象。

所以你应该做类似的事情

def __str__(self):
        return str(5)
Run Code Online (Sandbox Code Playgroud)

或者更好,更有意义的东西,比如

def __str__(self) -> str:
        return "TestObject with id: {}".format(self.id)
Run Code Online (Sandbox Code Playgroud)

(返回类型可以添加到函数声明中,这样你的编辑器就会让你知道它是否没有正确的类型。)

  • 该方法本身不会引发错误;它确实返回一个 int 。如果“__str__”方法返回非字符串,则“str”函数会引发错误。 (2认同)