class Node():
def __init__(self, data):
self.data=data
self.next_node=None
node0=Node("I")
node1=Node("heard")
node2=Node("there")
node3=Node("was")
node0.next_node=node1
node1.next_node=node2
node2.next_node=node3
class LinkedList():
def __init__(self, first_node: Node):
self.first_node=first_node
1. Node and LinkedList
Introduced previously.
ll = LinkedList(first_node=node0)2. Type-Annotations
I started using Type-Annotations (E.g. linked_list: LinkedList) in my function arguments:
- because when I typed something like
current_node.(an instance with a . attribute-accessor), then, - I will be presented with current_node’s attributes to choose from in Visual Studio Code (VSC).
- This is because of the linting by Pylance extension that comes with VSC.
Notice data and next_node are at the top of the list.

3. LinkedList: Read() at Index & Return Node.data
def read_ll_tp1(linked_list: LinkedList, idx: int) -> str | None:
current_node = linked_list.first_node
for i in range(idx):
# print(i)
current_node = current_node.next_node
if not current_node:
# raise IndexError("LinkedList exhausted!")
return None
return current_node.data
print(read_ll_tp1(ll,0))
print(read_ll_tp1(ll,1))
print(read_ll_tp1(ll,2))
print(read_ll_tp1(ll,3))
print(read_ll_tp1(ll,4))I
heard
there
was
None
4. LinkedList: Search() for Value & Return Index
def search_ll_tp1(linked_list: LinkedList, value: str) -> int | None:
current_node = linked_list.first_node
i=0
while current_node:
if current_node.data == value:
return i
current_node = current_node.next_node
# if not current_node: <- redundant since inside while current_node
# return None
i+=1
return None # <- if current_node is false return None
print(search_ll_tp1(ll,"I"))
print(search_ll_tp1(ll,"heard"))
print(search_ll_tp1(ll,"there"))
print(search_ll_tp1(ll,"was"))
print(search_ll_tp1(ll,"a"))0
1
2
3
None