Python: 为什么 __str__ 方法中的这个 AttributeError 在这个缩进改变后就消失了
Python: Why does this AttributeError in __str__ method disappear after this indentation change
我希望您能够在您的机器上重现此错误。当我将 __str__
方法与与方法相同的缩进对齐时,我无法弄清楚为什么下面的代码会给我一个错误 [此后粘贴]:__init__
和 addNeighbor
。我已经从这个 link 中编写了 class 的一部分,但在 __str__
中以不同的方式命名了我的变量。当我收到错误时,我只是粘贴了 link 中的代码并且它起作用了。
正是在这一点上,我意识到我对 __str__
方法的缩进与其他方法的缩进不一致。当我将所有内容都放入相同的缩进中时,我遇到了同样的错误,所以我将该方法返回到其先前的实现中并得到以下输出:<__main__.Vertex object at 0x1079b4128>
为什么会这样?我不应该从一开始就得到一个 IndentationError
吗?当我缩进我自己版本的 __str__
方法并给它更多的缩进时,我没有收到任何错误。为什么?谁能复制这个错误?
class Vertex:
def __init__(self, key):
self.id = key
self.connectedTo = {}
def addNeighbor(self, neighbor, weight=0):
self.connectedTo[neighbor] = weight
def __str__(self):
return str(self.id) + " connected to: " + str([vertex.id for vertex in self.connectedTo])
# def __str__(self):
# return str(self.id) + ' connectedTo: ' + str([x.id for x in self.connectedTo])
if __name__ == '__main__':
vertex = Vertex(1)
vertex.addNeighbor('1', 20)
vertex.addNeighbor('2', 10)
print(vertex)
我得到的错误是:
Traceback (most recent call last):
File "graph_implementation.py", line 19, in <module>
print(vertex)
File "graph_implementation.py", line 13, in __str__
return str(self.id) + ' connectedTo: ' + str([x.id for x in self.connectedTo])
File "graph_implementation.py", line 13, in <listcomp>
return str(self.id) + ' connectedTo: ' + str([x.id for x in self.connectedTo])
AttributeError: 'str' object has no attribute 'id'
这是因为使用缩进,__str__
是方法 addNeighbor
中的局部函数。仅在addNeighbor
范围内可见。如果没有自定义__str__
,则使用默认方法
原来的错误是因为x.id
中的x
是一个字符串(节点名)。字符串没有 id
属性。为了使您的代码正常工作,请将 vertex.addNeighbor('1', 20)
等更改为 vertex.addNeighbor(Vertex('1'), 20)
。
这里发生了一些事情。
首先,正如您所说,__str__
的缩进是错误的。但它仍然是 有效 缩进,这就是为什么你不会得到 IndentationError
的原因。该错误仅在调用 __str__
时出现,只有当它处于正确的缩进级别时才会发生,这是较小的缩进,符合 __init__
和 addNeighbor
。 (否则,它只是 addNeighbor
中的一个局部函数,而且毫无用处。)
调用 __str__
方法后,您得到的错误是由于 self.connectedTo
字典的结构。在 addNeighbor()
中,您正在映射 neighbor: weight
,其中 neighbor
作为 str
传入,权重作为 int
传入。当您像 [x.id for x in self.connectedTo]
那样遍历字典时,Python 将遍历该字典的 keys,在本例中为 neighbor
,a细绳。所以 x
变成了一个字符串。 (list comprehension 写成[x.id for x in self.connectedTo.keys()]
比较好,和原来的一样,但是更清晰。)
您链接的页面显示了最初的错误,即 neighbor
应该是另一个 Vertex
,而不是 str
。这意味着这一切都归结为将错误类型的参数传递给 addNeighbor()
。因此,考虑到这一点,我可能会像这样重写您的测试代码...
class Vertex:
def __init__(self, key):
self.id = key
self.connectedTo = {}
def addNeighbor(self, neighbor, weight=0):
self.connectedTo[neighbor] = weight
def __str__(self):
return str(self.id) + ' connectedTo: ' + str([x.id for x in self.connectedTo])
if __name__ == '__main__':
vertex = Vertex(1)
vertex.addNeighbor(Vertex(1), 20) # This creates a second Vertex with the same ID
# as `vertex` -- probably not what you intend?
vertex.addNeighbor(Vertex(2), 10)
print(vertex)
# Output:
1 connected to: [1, 2]
我希望您能够在您的机器上重现此错误。当我将 __str__
方法与与方法相同的缩进对齐时,我无法弄清楚为什么下面的代码会给我一个错误 [此后粘贴]:__init__
和 addNeighbor
。我已经从这个 link 中编写了 class 的一部分,但在 __str__
中以不同的方式命名了我的变量。当我收到错误时,我只是粘贴了 link 中的代码并且它起作用了。
正是在这一点上,我意识到我对 __str__
方法的缩进与其他方法的缩进不一致。当我将所有内容都放入相同的缩进中时,我遇到了同样的错误,所以我将该方法返回到其先前的实现中并得到以下输出:<__main__.Vertex object at 0x1079b4128>
为什么会这样?我不应该从一开始就得到一个 IndentationError
吗?当我缩进我自己版本的 __str__
方法并给它更多的缩进时,我没有收到任何错误。为什么?谁能复制这个错误?
class Vertex:
def __init__(self, key):
self.id = key
self.connectedTo = {}
def addNeighbor(self, neighbor, weight=0):
self.connectedTo[neighbor] = weight
def __str__(self):
return str(self.id) + " connected to: " + str([vertex.id for vertex in self.connectedTo])
# def __str__(self):
# return str(self.id) + ' connectedTo: ' + str([x.id for x in self.connectedTo])
if __name__ == '__main__':
vertex = Vertex(1)
vertex.addNeighbor('1', 20)
vertex.addNeighbor('2', 10)
print(vertex)
我得到的错误是:
Traceback (most recent call last):
File "graph_implementation.py", line 19, in <module>
print(vertex)
File "graph_implementation.py", line 13, in __str__
return str(self.id) + ' connectedTo: ' + str([x.id for x in self.connectedTo])
File "graph_implementation.py", line 13, in <listcomp>
return str(self.id) + ' connectedTo: ' + str([x.id for x in self.connectedTo])
AttributeError: 'str' object has no attribute 'id'
这是因为使用缩进,__str__
是方法 addNeighbor
中的局部函数。仅在addNeighbor
范围内可见。如果没有自定义__str__
,则使用默认方法
原来的错误是因为x.id
中的x
是一个字符串(节点名)。字符串没有 id
属性。为了使您的代码正常工作,请将 vertex.addNeighbor('1', 20)
等更改为 vertex.addNeighbor(Vertex('1'), 20)
。
这里发生了一些事情。
首先,正如您所说,__str__
的缩进是错误的。但它仍然是 有效 缩进,这就是为什么你不会得到 IndentationError
的原因。该错误仅在调用 __str__
时出现,只有当它处于正确的缩进级别时才会发生,这是较小的缩进,符合 __init__
和 addNeighbor
。 (否则,它只是 addNeighbor
中的一个局部函数,而且毫无用处。)
调用 __str__
方法后,您得到的错误是由于 self.connectedTo
字典的结构。在 addNeighbor()
中,您正在映射 neighbor: weight
,其中 neighbor
作为 str
传入,权重作为 int
传入。当您像 [x.id for x in self.connectedTo]
那样遍历字典时,Python 将遍历该字典的 keys,在本例中为 neighbor
,a细绳。所以 x
变成了一个字符串。 (list comprehension 写成[x.id for x in self.connectedTo.keys()]
比较好,和原来的一样,但是更清晰。)
您链接的页面显示了最初的错误,即 neighbor
应该是另一个 Vertex
,而不是 str
。这意味着这一切都归结为将错误类型的参数传递给 addNeighbor()
。因此,考虑到这一点,我可能会像这样重写您的测试代码...
class Vertex:
def __init__(self, key):
self.id = key
self.connectedTo = {}
def addNeighbor(self, neighbor, weight=0):
self.connectedTo[neighbor] = weight
def __str__(self):
return str(self.id) + ' connectedTo: ' + str([x.id for x in self.connectedTo])
if __name__ == '__main__':
vertex = Vertex(1)
vertex.addNeighbor(Vertex(1), 20) # This creates a second Vertex with the same ID
# as `vertex` -- probably not what you intend?
vertex.addNeighbor(Vertex(2), 10)
print(vertex)
# Output:
1 connected to: [1, 2]