4
class MyClass:
    def __init__(self):
        self.list_ = []
    def __repr__(self):
        return '\n'.join(['this','should','all','be','on','separate','lines']) + str([str(list_val) for list_val in self.list_])

myClass = MyClass()
myClass.list_.append(MyClass())
myClass.list_[0].list_.append(MyClass())
print(myClass)

我希望这段代码能打印出来:

this
should
all
be
on
separate
lines[this
should
all
be
on
separate
lines[this
should
all
be
on
separate
lines]]

或类似的东西,但它会打印

this
should
all
be
on
separate
lines["this\nshould\nall\nbe\non\nseparate\nlines['this\\nshould\\nall\\nbe\\non\\nseparate\\nlines[]']"]

也就是说,当我尝试__repr__在同一个类的另一个对象的方法中将一个对象转换为字符串时,它会将换行符转换为\n,如果我进一步嵌套它会导致\\n,并且每次嵌套它都会添加转义序列之前的附加反斜杠。

看完这个问题后,似乎该__repr__方法认为我实际上想要两个字符\and n,但我不:我想要转义序列\n。有没有办法覆盖它并强制它解释为换行符而不是两个单独的字符?

4

1 回答 1

7

问题是repr字符串的 将特殊字符转换为转义序列。这意味着如果您repr递归调用带有特殊字符的字符串,反斜杠将堆积起来:

>>> print("First line\nSecond line")
First line
Second line
>>> print(repr("First line\nSecond line"))
'First line\nSecond line'
>>> print(repr(repr("First line\nSecond line")))
"'First line\\nSecond line'"

您遇到这种情况是因为您在列表上__repr__调用str,并且列表中的每个项目都str使用repr( not ): str

>>> print('First line\nSecond line')
First line
Second line
>>> print(['First line\nSecond line'])
['First line\nSecond line']

请注意,\n这里出现了 ,就像repr在第一个示例中调用字符串本身一样。那是因为列表调用repr它们的内容来显示它们自己。

因此,通过这样做str([...]),您正在调用repr列表的内容,这意味着您正在repr递归调用嵌套对象,这意味着反斜杠堆积如您所见。

如果你想避免这种情况,你需要避免在嵌套对象上调用 repr。您可以通过使用 手动制作字符串来做到这一点join,类似于您已经做过的,而不是调用str列表:

def __repr__(self):
    innerRepr = '['+'\n'.join(str(list_val) for list_val in self.list_) + ']' if self.list_ else ''
    return '\n'.join(['this','should','all','be','on','separate','lines']) + innerRepr

然后你print(myClass)给出你想要的结果。

于 2015-12-31T05:05:58.753 回答