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 ,并且每次我嵌套它在转义序列之前添加了一个额外的反斜杠。

阅读 this question 后,似乎 __repr__ 方法认为我实际上想要 \n 两个字符,但我不想要:我想要转义序列 \n 。有什么方法可以覆盖它并强制它将其解释为换行符而不是两个单独的字符?

最佳答案

问题在于字符串的 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 (而不是 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) 给出你想要的结果。

关于Python - 嵌套的 __repr__ 将换行符恢复为 "\\n",我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34540919/

10-16 02:49