在Python中对__str__感到困惑

从Java背景来看,我明白__str__就像是toString的Python版本(虽然我知道Python是旧的语言)。

所以,我用__str__方法定义了一个__str__ ,如下所示:

 class Node: def __init__(self, id): self.id = id self.neighbours = [] self.distance = 0 def __str__(self): return str(self.id) 

然后我创build它的几个实例:

 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]] 

我错过了什么? 还有什么其他令我畏惧的东西呢? 🙂

Python有两种不同的方式将对象转换为string: str()repr() 。 打印一个对象使用str() ; 打印包含对象的列表使用str()作为列表本身,但是list.__str__()调用了单个项目的repr()

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

 __repr__ = __str__ 

在课堂结束的时候会做伎俩。

由于Python对Java的无限优越性,Python没有一个 ,而是两个 toString操作。

一个是__str__ ,另一个是__repr__

__str__将返回一个人类可读的string。 __repr__将返回一个内部表示。

可以通过调用repr(obj)或使用反引号`obj`来调用`obj`

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

它提供了可读的输出版本,而不是“对象”:例如:

 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 

那么容器对象的__str__方法将在其内容上使用repr ,而不是str 。 所以你可以使用__repr__而不是__str__ ,当你使用一个ID作为结果。

只有当对象需要string表示时才调用__str__

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

然而,还有另外一个叫做__repr__魔术方法,这是一个对象的表示 。 当你没有明确地将对象转换为一个string时,就使用了表示法。

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

关于类的事情,以及设置等同于类内某个值的不受阻碍的全局variables是,全局variables存储的实际上是对实际存储的内存位置的引用。

你在输出中看到的就是这个。

在你使用str初始全局variables的时候,由于str方法以及打印的工作原理,你可能会看到这个值,并且在没有问题的情况下使用print,所以你不能用list来做这件事,因为存储在元素在这个列表中只是对值的内存位置的引用 – 如果您想了解更多信息,请在别名上进行阅读。

另外,当使用列表并丢失什么是别名,什么不是,你可能会发现你正在改变原始列表元素的值,如果你在别名列表中改变它 – 因为再一次,当你设置一个列表元素等于列表中的列表或元素,新列表只存储对内存位置的引用(它实际上并不创build特定于新variables的新内存空间)。 这是deepcopy在哪里派上用场!

打印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