124

来自 Java 背景,我理解这__str__类似于 Python 版本的 toString(虽然我确实意识到 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)

现在,尝试打印这些对象之一时的预期行为是打印它的关联值。这也会发生。

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 有两种不同的方式将对象转换为字符串:str()repr(). 打印对象使用str(); 打印包含对象str()的列表用于列表本身,但list.__str__()调用repr()单个项目的实现。

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

__repr__ = __str__

在类主体的最后会做的伎俩。

于 2012-09-16T15:33:30.720 回答
44

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

一个是__str__,另一个是__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中阅读,str关于list每个项目的调用__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)

注意:与和或print repr(uno)的正确实现一起允许重新创建对象并检查是否相等。__eq____ne____cmp__

于 2018-02-11T14:24:08.280 回答
9

好吧,容器对象的__str__方法将用于repr它们的内容,而不是str. 因此,您可以使用__repr__而不是__str__,因为您使用的是 ID 作为结果。

于 2012-09-16T15:33:16.810 回答
4

__str__仅当对象需要字符串表示时才调用。

例如str(uno)print "%s" % unoprint uno

但是,还有另一种称为__repr__this 的魔术方法是对象的表示。当您没有将对象显式转换为字符串时,将使用表示

如果你这样做,uno.neighbors.append([[str(due),4],[str(tri),5]])它会做你所期望的。

于 2012-09-16T15:34:51.413 回答
1

关于类的事情,以及设置未占用的全局变量等于类中的某个值,是你的全局变量存储的实际上是对实际存储值的内存位置的引用。

您在输出中看到的内容表明了这一点。

由于str方法以及 print 的工作原理,您可能可以在使用初始全局变量时看到值并使用 print 而不会出现问题,但您将无法使用列表执行此操作,因为存储在元素中的内容在该列表中只是对值的内存位置的引用——如果您想了解更多信息,请阅读别名。

此外,当使用列表并忘记什么是别名和什么不是别名时,如果您在别名列表中更改它,您可能会发现您正在更改原始列表元素的值 - 因为同样,当您设置列表元素等于列表或列表中的元素,新列表仅存储对内存位置的引用(它实际上并不创建特定于该新变量的新内存空间)。这就是 deepcopy 派上用场的地方!

于 2017-02-16T13:13:00.470 回答
-1

printself.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 回答