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__メソッドは、私が実際に 2 つの文字\とを必要としていると考えているようですnが、私はそうではありません: I want the escape sequence \n. これをオーバーライドして、2 つの個別の文字ではなく改行として解釈するように強制する方法はありますか?

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__呼び出しと、リストのがリスト内の各項目で( not ) を使用しているためです。strstrrepr 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 に答える