Python - 嵌套__repr__将换行符恢复为" \\ n"

时间:2015-12-31 04:18:27

标签: python string recursion escaping repr

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。有没有办法覆盖它并强制它将其解释为换行符而不是两个单独的字符?

1 个答案:

答案 0 :(得分:4)

问题是字符串的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不是 { {1}})列表中的每个项目:

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 会提供您想要的结果。