Ошибка атрибута: нет объекта типа в связанном списке

Я попытался создать простой односвязный список следующим образом:

class node:
    def __init__(self, data=None):
        self.data = data
        self.next = None


class linkedlist:
    def __init__(self):
        self.head = node()

    def append(self, data):
        curr = self.head
        new_node = node(data)
        while curr.next != None:
            curr = curr.next
        curr.next = new_node

    def total(self):
        curr = self.head
        total = 0
        while curr.next != None:
            curr = curr.next
            total += 1
        return total

    def display(self):
    # added total here as well
        curr = self.head
        em = []
        total = 0
        while curr.next != None:
            curr = curr.next
            em.append(curr.data)
            total += 1
        print(f"LinkedList: {em} \n Total: {self.total()}  ")

    def look(self, index):
        if index >= self.total():
            print("ERROR: Index error" )
        curr_index = self.head
        idx = 0
        while True:
            curr_index = curr_index.next
            if idx == index:
                print(curr_index.data)
            idx += 1

Всякий раз, когда я вызываю функцию look(), я получаю следующую ошибку:

curr_index = curr_index.next
             ^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'next'

Что это может означать?

Насколько я знаю, curr_index использует self.head, который, в свою очередь, использует node(). У node() есть атрибут next.

Этой ошибки нет, когда я вызываю другие функции класса. Более того, другие функции, за исключением функции look(), возвращают соответствующие значения без ошибок.

Где мой код идет не так?

while True: Цикл бесконечен
KamilCuk 28.06.2024 19:51

Измените его на пока while curr_index.next:

user24714692 28.06.2024 19:53

«Что это может означать?»: это означает, что curr_index есть None и None не имеет атрибута next.

trincot 28.06.2024 19:54
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
3
60
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

В этой реализации каждый узел указывает на следующий узел списка, а последний указывает на None, что означает конец списка.

Цикл в look пытается перебирать узлы, пока не дойдет до index-го элемента, а затем печатает его, но на этом цикл не завершается. Фактически, он будет продолжаться бесконечно, пока в какой-то момент не пройдет последний элемент, создав текущий элемент None, а затем произойдет сбой с этой ошибкой. Один из подходов — явно завершить цикл, как только вы достигнете нужного элемента:

def look(self, index):
    if index >= self.total():
        # Need to throw here, not just print
        # because printing out an error won't prevent the function from moving on
        throw ValueError("ERROR: Index error")

    curr_index = self.head
    idx = 0
    while True:
        curr_index = curr_index.next
        if idx == index:
            print(curr_index.data)
            return # We're done here, return
        idx += 1

При этом проверка idx == index на каждой итерации является излишней. Вы можете просто заранее curr_indexindex раз явно указать:

def look(self, index):
    if index >= self.total():
        # Need to throw here, not just print
        # because printing out an error won't prevent the function from moving on
        throw ValueError("ERROR: Index error")

    curr_index = self.head
    for _ in range(index):
        curr_index = curr_index.next

    print(curr_index.data)

Ошибка в этом коде возникает из-за того, что вы указали метод while True внутри look(), в котором цикл будет бесконечным, поэтому он обращается к указателю next узла, которого нет в связанном списке, поэтому отображается ошибка.

Решение :-

# Change while True: to while curr_index:

def look(self, index):
    if index >= self.total():
        print("ERROR: Index error" )
    curr_index = self.head
    idx = 0
    while curr_index:
        curr_index = curr_index.next
        if idx == index:
            print(curr_index.data)
        idx += 1

Я надеюсь, что это было полезно для вас.

Другие вопросы по теме