Python: почему этот AttributeError в методе __str__ исчезает после этого изменения отступа - PullRequest
0 голосов
/ 05 мая 2018

Я надеюсь, что вы сможете повторить эту ошибку на вашем компьютере. Я не мог понять, почему именно приведенный ниже код дал мне ошибку [вставленную после этого], когда у меня был __str__ метод, выровненный с тем же отступом, что и методы: __init__ и addNeighbor. Я написал часть класса по этой ссылке , но назвал мои переменные в __str__ по-другому. Когда я получил ошибку, я просто вставил код по ссылке, и она заработала.

Именно в этот момент я понял, что мои отступы для метода __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'

Ответы [ 2 ]

0 голосов
/ 05 мая 2018

Здесь происходит несколько вещей.

Прежде всего, как вы сказали, ваше отступление от __str__ неверно. Но это все равно действительный отступ, поэтому вы не получите IndentationError. Ошибка появляется только тогда, когда вызывается __str__, что происходит только при правильном уровне отступа, который является меньшим отступом, в соответствии с __init__ и addNeighbor. (В противном случае, это просто локальная функция внутри addNeighbor и довольно бесполезная.)

Как только вызывается метод __str__, вы получаете ошибку из-за структуры словаря self.connectedTo. В addNeighbor() вы отображаете neighbor: weight, где neighbor передается как str, а вес как int. Когда вы перебираете словарь, как в [x.id for x in self.connectedTo], Python будет перебирать ключи этого словаря, который в данном случае является neighbor, строкой. Так x становится строкой. (Понимание списка лучше записать как [x.id for x in self.connectedTo.keys()], что эквивалентно оригиналу, но более четкое.)

На странице, на которую вы ссылались, указана первоначальная ошибка, хотя & ndash; а именно, что 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]
0 голосов
/ 05 мая 2018

Это потому, что с вашим отступом __str__ является локальной функцией в методе addNeighbor. Это видно только в объеме addNeighbor. В отсутствие пользовательского __str__ используется метод по умолчанию.

Первоначальная ошибка произошла из-за того, что x в x.id является строкой (имя узла). Строки не имеют атрибута id. Чтобы ваш код работал, измените vertex.addNeighbor('1', 20) и т. П. На vertex.addNeighbor(Vertex('1'), 20).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...