# Singly Linked List Implementation in Python

In this article, we will learn what is singly linked list is and its implementation using Python.
The singly linked list is a linear data structure in which each element of the list contains a pointer that points to the next element in the list. Each element in the singly linked list is called a node. Each node has two components: data and a pointer next which points to the next node in the list.
The first node of the list is called a head, and the last node of the list is called a tail. The last node of the list contains a pointer to the null. Each node in the list can be accessed linearly by traversing through the list from head to tail.

# Singly Linked List Implementation in Python

``````from typing import Any

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

def __repr__(self) -> str:
return f"Node({self.data})"

def __init__(self):

def __iter__(self) -> Any:

while node:
yield node.data
node = node.next

def __len__(self) -> int:
return len(tuple(iter(self)))

def __repr__(self) -> str:
return "->".join([str(item) for item in self])

def __getitem__(self, index: int) -> Any:
if not 0 <= index < len(self):
raise ValueError("list index out of range.")
for i, node in enumerate(self):
if i == index:
return node

# Used to change the data of a particular node
def __setitem__(self, index: int, data: Any) -> None:
if not 0 <= index < len(self):
raise ValueError("list index out of range.")
for i in range(index):
current = current.next
current.data = data

def insert_tail(self, data: Any) -> None:
self.insert_nth(len(self), data)

def insert_head(self, data: Any) -> None:
self.insert_nth(0, data)

def insert_nth(self, index: int, data: Any) -> None:
if not 0 <= index <= len(self):
raise IndexError("list index out of range")
new_node = Node(data)
elif index == 0:
else:
for _ in range(index - 1):
temp = temp.next
new_node.next = temp.next
temp.next = new_node

def print_list(self) -> None:  # print every node data
print(self)

return self.delete_nth(0)

def delete_tail(self) -> Any:  # delete from tail
return self.delete_nth(len(self) - 1)

def delete_nth(self, index: int = 0) -> Any:
if not 0 <= index <= len(self) - 1:  # test if index is valid
raise IndexError("List index out of range.")
delete_node = self.head  # default first node
if index == 0:
else:
for _ in range(index - 1):
temp = temp.next
delete_node = temp.next
temp.next = temp.next.next
return delete_node.data

def is_empty(self) -> bool:

def reverse(self) -> None:
prev = None

while current:
# Store the current node's next node.
next_node = current.next
# Make the current node's next point backwards
current.next = prev
# Make the previous node be the current node
prev = current
# Make the current node the next node (to progress iteration)
current = next_node
# Return prev in order to put the head at the end

def main():
print("\nPrint list:")
print("\nPrint list:")
print("Delete tail")
print("\nPrint list:")
print("\nPrint list:")
linked_list[1] = input("Enter New Value: ").strip()
print("New list:")

if __name__ == "__main__":
main()
``````

Output:

``````Inserting 1st at head 10

Print list:
20->10

Inserting 1st at tail 30
Inserting 2nd at tail 40

Print list:
20->10->30->40

Delete tail

Print list:
10->30

Print list:
30->10