marifkind
marifkind

Reputation: 125

Class Function Not Finding Positional Argument Self in Python

I created a linked list class in Python and when calling the size function in which I defined, I am getting the following error:

TypeError: get_next() missing 1 required positional argument: 'self'

I tried calling another function in which I defined that also uses the get_next() function and it did not produce the error. Below is the Class definition as well as the test code.

LinkedLists.py:

class Node(object):
    def __init__(self, data = None, next_node = None):
        self.data = data
        self.next_node = next_node

    def get_data(self):
        return self.data

    def get_next(self):
        return self.next_node

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

class LinkedList(object):
    def __init__(self, head = Node):
        self.head = head

    def insert(self, data):
        new_node = Node(data)

        new_node.set_next(self.head)
        self.head = new_node

    def size(self):
        current = self.head
        count = 0

        while current:
            count += 1
            current = current.get_next()

        return count

    def search(self, data):
        current = self.head
        found = False

        while current:
            if current.get_data() == data:
                found = True
            else:
                current = current.get_next()

        if current is None:
            raise ValueError("Data not in list")

        return current

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

        while current and found is False:
            if current.get_data() == data:
                found = True
            else:
                previous = current
                current = current.get_next()

        if current is None:
            raise ValueError("Data not in list")

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

    def insert_at(self, data, location):
        new_node = Node(data)
        current = self.head
        found = False

        while current and found is False:
            if current.get_data() == data:
                found = True
            else:
                current = current.get_next()

            if current is None:
                raise ValueError("Data not in list")

            new_node.set_next(current.get_next())

            current.set_next(new_node)

LinkedListsTest.py:

from LinkedLists import *

List = LinkedList()

List.insert(5)
List.insert(6)
List.insert(8)
List.delete(6)

print(List.size())

The full traceback of the error:

Traceback (most recent call last):
  File "LinkedListsTest.py", line 10, in <module>
    print(List.size())
  File ".../LinkedLists.py", line 31, in size
    current = current.get_next()
TypeError: get_next() missing 1 required positional argument: 'self'

Upvotes: 0

Views: 752

Answers (2)

Martijn Pieters
Martijn Pieters

Reputation: 1123620

You set self.head to the Node class, not an instance:

def __init__(self, head = Node):
    self.head = head

Note the Node reference there. Node.get_next() calls the unbound method and no self is passed in.

However, don't set head=Node() as a default; defaults are set once, at function definition time, and a mutable default will cause you issues as all instances of your LinkedList class will share that one instance. See "Least Astonishment" and the Mutable Default Argument.

Use a sentinel like None instead to detect you need to create a default:

def __init__(self, head=None):
    if head is None:
        # create an empty default
        head = Node()
    self.head = head

With this correction, your test prints 3.

Upvotes: 2

quamrana
quamrana

Reputation: 39404

Assuming I have correctly interpreted the correct indentation, I think you may have the default parameter incorrect:

class LinkedList(object):
    def __init__(self, head = Node()): # <== default should be instance
        self.head = head

However, this can produce surprising results. You may have meant this:

class LinkedList(object):
    def __init__(self, head = None):
        if head is None:
            head = Node()
        self.head = head

Upvotes: 1

Related Questions