124

Javaのバックグラウンドから来て、私__str__はそれがtoStringのPythonバージョンのようなものであることを理解しています(Pythonが古い言語であることは理解していますが)。

__str__そこで、次のようにメソッドとともに小さなクラスを定義しました。

class Node:

    def __init__(self, id):
        self.id = id
        self.neighbours = []
        self.distance = 0


    def __str__(self):
        return str(self.id)

次に、そのインスタンスをいくつか作成します。

uno = Node(1)    
due = Node(2)    
tri = Node(3)    
qua = Node(4)

現在、これらのオブジェクトの1つを印刷しようとしたときに予想される動作は、関連付けられた値が印刷されることです。これも起こります。

print uno

収量

1

しかし、私が次のことをするとき:

uno.neighbours.append([[due, 4], [tri, 5]])

その後

print uno.neighbours

私は得る

[[[<__main__.Node instance at 0x00000000023A6C48>, 4], [<__main__.Node instance at 0x00000000023A6D08>, 5]]]

期待したところ

[[2, 4], [3, 5]]

私は何が欠けていますか?そして、他に何をしているのですか?:)

4

8 に答える 8

149

Pythonには、オブジェクトを文字列に変換する2つの異なる方法があります。str()repr()。オブジェクトの印刷にはstr();を使用します。オブジェクトを含むリストを印刷するstr()と、リスト自体が使用されますが、個々のアイテムのlist.__str__()呼び出しが実装されます。repr()

したがって、も上書きする必要があります__repr__()。シンプルな

__repr__ = __str__

クラスの最後にボディがトリックを行います。

于 2012-09-16T15:33:30.720 に答える
44

PythonはJavaよりも無限に優れているため、Pythonには1つではなく2つのtoString操作があります。

1つは__str__、もう1つは__repr__

__str__人間が読める文字列を返します。 __repr__内部表現を返します。

__repr__を呼び出すrepr(obj)か、バッククォートを使用して、オブジェクトに対して呼び出すことができます`obj`

リストや他のコンテナクラスを印刷する場合、含まれている要素はを使用して印刷され__repr__ます。

于 2012-09-16T15:37:38.473 に答える
25

「オブジェクト」ではなく、人間が読める形式の出力を提供します。例:

class Pet(object):

    def __init__(self, name, species):
        self.name = name
        self.species = species

    def getName(self):
        return self.name

    def getSpecies(self):
        return self.species

    def Norm(self):
        return "%s is a %s" % (self.name, self.species)

if __name__=='__main__':
    a = Pet("jax", "human")
    print a 

戻り値

<__main__.Pet object at 0x029E2F90>

「 str 」を含むコードは別の何かを返します

class Pet(object):

    def __init__(self, name, species):
        self.name = name
        self.species = species

    def getName(self):
        return self.name

    def getSpecies(self):
        return self.species

    def __str__(self):
        return "%s is a %s" % (self.name, self.species)

if __name__=='__main__':
    a = Pet("jax", "human")
    print a 

戻り値:

jax is a human
于 2016-01-12T12:04:58.460 に答える
11

質問への回答

別の回答で指摘されているように、またPEP 3140で読むことができるように、各アイテムstrlist呼び出しについて__repr__。その部分についてできることはあまりありません。

を実装__repr__すると、より説明的なものが得られますが、正しく実装されている場合は、期待どおりではありません。

適切な実装

高速ですが間違った解決策は、にエイリアス__repr__すること__str__です。

__repr____str__ 無条件に設定しないでください。同じ値でオブジェクトを再作成するために使用できる有効なPython式のように見える表現を__repr__作成する必要があります。この場合、これはではなくになります。Node(2)2

の適切な実装により__repr__、オブジェクトを再作成できます。この例では、やなどの他の重要なメンバーも含まれている必要がありneighoursますdistance

不完全例:

class Node:

    def __init__(self, id, neighbours=[], distance=0):
        self.id = id
        self.neighbours = neighbours
        self.distance = distance


    def __str__(self):
        return str(self.id)


    def __repr__(self):
        return "Node(id={0.id}, neighbours={0.neighbours!r}, distance={0.distance})".format(self)
        # in an elaborate implementation, members that have the default
        # value could be left out, but this would hide some information


uno = Node(1)    
due = Node(2)    
tri = Node(3)    
qua = Node(4)

print uno
print str(uno)
print repr(uno)

uno.neighbours.append([[due, 4], [tri, 5]])

print uno
print uno.neighbours
print repr(uno)

:およびprint repr(uno)の適切な実装とともに、オブジェクトを再作成して等しいかどうかを確認できます。__eq____ne____cmp__

于 2018-02-11T14:24:08.280 に答える
9

さて、コンテナオブジェクトの__str__メソッドはrepr、ではなく、そのコンテンツで使用しstrます。したがって、結果としてIDを使用していることを確認して、__repr__の代わりにを使用できます。__str__

于 2012-09-16T15:33:16.810 に答える
4

__str__オブジェクトに文字列表現が必要な場合にのみ呼び出されます。

たとえばstr(uno)print "%s" % unoまたはprint uno

__repr__ただし、これと呼ばれる別の魔法の方法がオブジェクトの表現です。オブジェクトを明示的に文字列に変換しない場合は、表現が使用されます。

これを行うuno.neighbors.append([[str(due),4],[str(tri),5]])と、期待どおりの結果が得られます。

于 2012-09-16T15:34:51.413 に答える
1

クラスに関すること、およびクラス内のある値に等しい障害のないグローバル変数を設定することは、グローバル変数が実際に格納するのは、値が実際に格納されるメモリ位置への参照であるということです。

出力に表示されているのは、これを示しています。

strメソッドとprintの動作により、使用した初期グローバル変数で問題なく値を確認してprintを使用できる場合、要素に格納されているものがあるため、リストではこれを実行できません。そのリスト内には、値のメモリ位置への参照が含まれています。詳細を知りたい場合は、エイリアスを確認してください。

さらに、リストを使用してエイリアスとは何かを追跡できなくなった場合、エイリアスリストで変更すると、元のリスト要素の値が変更されていることに気付く可能性があります。リスト要素がリストまたはリスト内の要素と等しい場合、新しいリストはメモリ位置への参照のみを格納します(実際には、その新しい変数に固有の新しいメモリ空間は作成されません)。これは、ディープコピーが役立つところです!

于 2017-02-16T13:13:00.470 に答える
-1

印刷self.id.__str__()はあなたにとってはうまくいくでしょうが、あなたにとってはそれほど有用ではありません。

プログラム__str__の開発中にグリッドまたは構造体表現を印刷したい場合は、このメソッドの方が便利です。

print self._grid.__str__()

def __str__(self):
    """
    Return a string representation of the grid for debugging.
    """
    grid_str = ""
    for row in range(self._rows):
        grid_str += str( self._grid[row] )
        grid_str += '\n'
    return grid_str
于 2014-09-12T02:46:05.523 に答える