在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" % uno
或print 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