为什么Python中的线性化给出了这个奇怪的结果呢?

时间:2018-03-12 14:26:27

标签: python python-3.x multiple-inheritance

考虑这种简化情况:

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列表中交换Decoderbytes),永远不会调用Decoder.__str__()

是什么给出了?

2 个答案:

答案 0 :(得分:2)

Comment(b'foo')调用Comment.__new__,未定义,会解析为Decoder.__new__bytes.__new__,具体取决于您在{定义Comment中列出它们的顺序{1}}。

Comment的MRO是CommentbytesDecoderobject。但是,实际调用的函数是:

  1. Comment.__new__,用于创建新对象。由于该函数未定义,我们接下来调用已定义的bytes.__new__。它实际上只是调用object.__new__(Comment, b'foo'),为您提供最终对象。

  2. 显示 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