为什么 Python 中的线性化会给出这种奇怪的结果?

Why does linearization in Python give this bizarre result?

考虑这个简化的情况:

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() 中的顺序如何(即我可以在超类列表中交换 Decoderbytes),永远不会调用 Decoder.__str__()

什么给了?

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

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

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

  2. 为了显示Comment的return值,解释器试图调用Comment.__repr__,而不是Comment.__str__。同样,该函数未定义,因此它返回到 bytes.__repr__,给出观察到的结果。

如果您使用打印功能,您会得到预期的结果,但如果您从控制台查看结果,您会看到 __repr__ 方法的结果。如果你需要它以这种方式工作,你可以从 __repr__

调用 self.__str__()
>>msg = Comment(b'foo')
>>msg
b'foo'
>>print(msg)  # or str(msg)
'#foo'

在那里你可以阅读它是如何工作的docs