为什么 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()
中的顺序如何(即我可以在超类列表中交换 Decoder
和 bytes
),永远不会调用 Decoder.__str__()
。
什么给了?
Comment(b'foo')
调用 Comment.__new__
,它未定义,解析为 Decoder.__new__
或 bytes.__new__
,具体取决于您在定义中列出它们的顺序Comment
.
Comment
的 MRO 是 Comment
、bytes
、Decoder
、object
。但是,实际调用的函数是:
Comment.__new__
,创建一个新对象。由于该函数未定义,我们接下来调用已定义的 bytes.__new__
。它实际上只是调用 object.__new__(Comment, b'foo')
,为您提供最终对象。
为了显示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
考虑这个简化的情况:
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()
中的顺序如何(即我可以在超类列表中交换 Decoder
和 bytes
),永远不会调用 Decoder.__str__()
。
什么给了?
Comment(b'foo')
调用 Comment.__new__
,它未定义,解析为 Decoder.__new__
或 bytes.__new__
,具体取决于您在定义中列出它们的顺序Comment
.
Comment
的 MRO 是 Comment
、bytes
、Decoder
、object
。但是,实际调用的函数是:
Comment.__new__
,创建一个新对象。由于该函数未定义,我们接下来调用已定义的bytes.__new__
。它实际上只是调用object.__new__(Comment, b'foo')
,为您提供最终对象。为了显示
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