在Python的列表中对__str__感到困惑

Chr*_*son 113 python printing string list tostring

来自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)
Run Code Online (Sandbox Code Playgroud)

然后我创建了一些它的实例:

uno = Node(1)    
due = Node(2)    
tri = Node(3)    
qua = Node(4)
Run Code Online (Sandbox Code Playgroud)

现在,尝试打印其中一个对象时的预期行为是打印相关值.这也发生了.

print uno
Run Code Online (Sandbox Code Playgroud)

产量

1
Run Code Online (Sandbox Code Playgroud)

但是当我做以下事情时:

uno.neighbours.append([[due, 4], [tri, 5]])
Run Code Online (Sandbox Code Playgroud)

然后

print uno.neighbours
Run Code Online (Sandbox Code Playgroud)

我明白了

[[[<__main__.Node instance at 0x00000000023A6C48>, 4], [<__main__.Node instance at 0x00000000023A6D08>, 5]]]
Run Code Online (Sandbox Code Playgroud)

在哪里我期待

[[2, 4], [3, 5]]
Run Code Online (Sandbox Code Playgroud)

我错过了什么?还有什么其他令人讨厌的东西我在做什么?:)

Sve*_*ach 139

Python有两种不同的方法将对象转换为字符串:str()repr().打印对象使用str(); 打印包含对象str()的列表用于列表本身,但是执行对各个项的list.__str__()调用repr().

所以你也应该覆盖__repr__().一个简单的

__repr__ = __str__
Run Code Online (Sandbox Code Playgroud)

在课堂结束时会做到这一点.

  • 当没有`__str __()`时调用`__repr __()`,就足以定义`__repr __()`. (29认同)
  • 不应无条件地将__repr__设置为__str__。__repr__应该创建一个“ [表示形式,它看起来应该像一个有效的Python表达式,可以用来重新创建具有相同值的对象](https://docs.python.org/2/reference/datamodel.html?高亮= __ repr __#object .__ repr__)“在这种情况下,它更像是Node(2)而不是2。 (2认同)

Han*_*hen 37

由于Python相对于Java的无限优势,Python没有一个,而是两个 toString操作.

一个是__str__,另一个是__repr__

__str__将返回一个人类可读的字符串. __repr__将返回内部表示.

__repr__可以通过调用repr(obj)或使用反引号在对象上调用`obj`.

打印列表以及其他容器类时,将使用打印包含的元素__repr__.

  • 我意识到我正在追求冒犯幽默挑战的可能性.我以为我没有越线.你觉得我应该编辑我的帖子吗? (11认同)
  • 通常很难分辨讽刺和讽刺之间的区别 - 这可以解释为什么你的其他方面可以接受的答案从来没有收到过很多上升票.关于"幽默挑战"的评论可能也没有任何帮助. (9认同)
  • 请注意,作为`repr()的缩写的反引号在Python 3中消失了.轻微的挑剔:你的第一句话容易被那些把事情当回事的人误解. (7认同)

jax*_*jax 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 
Run Code Online (Sandbox Code Playgroud)

回报

<__main__.Pet object at 0x029E2F90>
Run Code Online (Sandbox Code Playgroud)

而带有" 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 
Run Code Online (Sandbox Code Playgroud)

收益:

jax is a human
Run Code Online (Sandbox Code Playgroud)


小智 9

那么,容器对象的__str__方法将使用repr其内容,而不是str.因此,您可以使用__repr__而不是__str__,因为您正在使用ID作为结果.


tra*_*cki 6

回答问题

正如另一位代表指出的答案,正如你可以在阅读PEP 3140,strlist每个项目的呼叫__repr__.关于那部分,你无能为力.

如果实施__repr__,您将获得更具描述性的内容,但如果实施得当,则不完全符合您的预期.

正确实施

快,但错误的解决方法是别名__repr____str__.

__repr__不应该__str__ 无条件地设置.__repr__应该创建一个表示,它应该看起来像一个有效的Python表达式,可用于重新创建具有相同值的对象.在这种情况下,这宁愿Node(2)2.

正确的实现__repr__可以重新创建对象.在此示例中,它还应包含其他重要成员,如neighoursdistance.

一个不完整的例子:

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)
Run Code Online (Sandbox Code Playgroud)

注意:print repr(uno)与正确实现__eq__和/ __ne____cmp__将允许重新创建对象并检查相等性.