考虑这种简化情况:
class Decoder:
def __str__(self):
return self.__bytes__().decode('ascii')
class Comment(Decoder, bytes):
def __bytes__(self):
return b'#' + self
用法:
Comment(b'foo')
打印:
b'foo'
而非预期:
#foo
无论Comment.mro()
中的顺序如何(即我可以在supeclass列表中交换Decoder
和bytes
),永远不会调用Decoder.__str__()
。
是什么给出了?
答案 0 :(得分:2)
Comment(b'foo')
调用Comment.__new__
,未定义,会解析为Decoder.__new__
或bytes.__new__
,具体取决于您在{定义Comment
中列出它们的顺序{1}}。
Comment
的MRO是Comment
,bytes
,Decoder
,object
。但是,实际调用的函数是:
Comment.__new__
,用于创建新对象。由于该函数未定义,我们接下来调用已定义的bytes.__new__
。它实际上只是调用object.__new__(Comment, b'foo')
,为您提供最终对象。
要显示 Comment
的返回值,解释程序会尝试拨打Comment.__repr__
,而不是Comment.__str__
。同样,函数没有被定义,所以它回退到bytes.__repr__
,给出了观察到的结果。
答案 1 :(得分:0)
如果使用打印功能,则会得到预期的结果,但如果从控制台查看结果,则会看到__repr__
方法的结果。如果您需要,可以通过self.__str__()
__repr__
>>msg = Comment(b'foo')
>>msg
b'foo'
>>print(msg) # or str(msg)
'#foo'
在那里,您可以阅读它的工作原理docs