prance
prance

Reputation: 157

Python Linked List - AttributeError: 'NoneType' object has no attribute 'get_data' with delete Function

I'm new to python and have been trying to learn simple data structures. I've been able to hack together some functions for a linked list and have been having trouble with my delete function. Heres list with the function in question and the test case: class Node: def init(self, initial_data): self.data = initial_data self.next = None

def get_data(self):
    return self.data

def get_next(self):
    return self.next

def set_data(self, new_data):
    self.data = new_data

def set_next(self, new_next):
    self.next = new_next

class LinkedList: def init(self): self.head = None

def __str__(self):
    output_string = ''

    current = self.head
    while current is not None:
        output_string += str(current.get_data())
        next_node = current.get_next()
        #gives the pointer to the next node i.e. the next node is that which is next to the current

        if next_node is not None:
            output_string += "->"

        current = next_node

    return output_string
#does not need to be changed for ordered linked list
def is_empty(self):
    if self.head is None:
        return True
    else:
        return False
def insert(self, data):
    current = self.head
    previous = None
    stop = False
    while current != None and not stop:
        if current.get_data() > data:
            stop = True
        else:
            previous = current
            current = current.get_next()
    temp = Node(data)
    if previous == None:
        temp.set_next(self.head)
        self.head = temp
    else:
        temp.set_next(current)
        previous.set_next(temp)



#does not need to be changed for ordered linked list
def size(self):
    current = self.head
    count = 0
    while current != None:
        count += 1
        current = current.get_next()
    return count
def search(self, item):
    current = self.head
    found = False
    stop = False

    while current is not None and not found and not stop:
        if current.get_data() == item:
            found = True

        else:
            current = current.get_next()
    return found

def delete(self, item):     
    current = self.head
    previous = None
    found = False

    while not found:
        if current.get_data() == item:
            found = True
        else:
            previous = current
            current = current.get_next()

    if previous is None:
        self.head = current.get_next()
    else:
        previous.set_next(current.get_next())

def test_nonexistent():
    my_list = LinkedList()
    my_list.insert(31)
    my_list.insert(77)
    my_list.insert(17)
    my_list.insert(93)
    my_list.insert(26)
    my_list.insert(54)
    assert my_list.size() == 6
    my_list.delete(77)
    my_list.delete(1)
    assert my_list.size() == 5

I get the error message

"AttributeError: 'NoneType' object has no attribute 'get_data' with delete Function"

I believe there is something wrong with the delete function as it can't handle a value thats isn't in the list, but I'm stumped as to how to get it to work at this point. Any help is appreciated!

Upvotes: 1

Views: 11031

Answers (2)

cangoektas
cangoektas

Reputation: 719

It's a bit hard to figure this out as you haven't posted the actual LinkedList but I assume that you are calling current.get_next() too many times and you probably reach the end of the list. Maybe something like this does the magic for you (UPDATE):

def delete(self, item):     
    current = self.head # we don't need the previous variable
    previous = None
    found = False
    while current is not None and not found:
        if current.get_data() == item:
            found = True
        else:
            previous = current
            current = current.get_next()
    # at this point we should have either reached to end of the list
    # and current is None
    # or we have found the node we were looking for
    if found and previous is not None:
        # delete it
        previous.set_next(current.get_next())
    elif found and previous is None:
        # removing head element
        self.head = None
    else:
        # nothing found
        print("Do whatever you want here")

Upvotes: 0

kindall
kindall

Reputation: 184151

You are using None to indicate there are no further nodes in the list, i.e. that you're at the end, but you never test for that when you're searching the list, so when you reach the end you try to call None.get_data(). Solution: don't do that.

A good way to rework the loop might be to change the while loop to test current and use break to exit the loop when the item is found.

while current is not None:
    if current.get_data() == item:
        break
    else:
        previous = current
        current = current.get_next()

You'll need to redo some of the later logic to account for this. You don't need the separate found flag; you can simply check current. If it's None, you reached the end of the list without finding the item you were looking for. Otherwise, you found it, and current is it.

Upvotes: 0

Related Questions