FAQ: Linked Lists: Python - Linked Lists Implementation II

Right, but if we use repr then we can just print() instead of calling the function each time.

1 Like

Is there any advantage to using the getter and setter methods over just referencing the class’s arguments?
For example, if you had to set a new “next_node” is there a difference between doing it like this:
my_node.next_node = new_next_node
or like this:
my_node.set_next_node(new_next_node)

Thanks!

2 Likes

Does anyone know why in this exercise they use the value as the parameter to check if we are at the end of the LinkedList instead of the actual pointer? I find it confusing, because the value of a node could actually be None right? While the pointer will be None for sure when we are at the tail of the LinkedList.

Another issue I am having is the actual code. Working with the .get_value() as the parameter to stop the While loop, I wrote the following:

def stringify_list(self):
    string_list = ""
    current_node = self.get_head_node()
    while current_node.get_value() != None:
      string_list += str(current_node.get_value()) + "/n"
      current_node = current_node.get_next_node()
    return string_list

The only difference with the solution is that I include the conditional directly onto the While loop line as opposed to setting an if statement afterwords. Why this doesn’t work? Thankss

1 Like

That’s a good question. You are correct that one might find one or more nodes having a value of None. The solution works fine without any reference to the value of the next or current one. All that is needed is a check on the existence of next_node.

## From the "Solution"
(1)    while current_node:
(2)      if current_node.get_value() != None:   # This line is unnecessary
(3)        string_list += str(current_node.get_value()) + "\n"
(4)      current_node = current_node.get_next_node()   
(5)    return string_list
  • Line 2 does nothing but, as noted by @waiseheil, confuse things if you have a few nodes having a value of None.

  • Line 4 is key, since the __init__ method of node sets a default next_node as None … This (None) is next_node, it is not the value of next_node.

  • … So when we get to the node where n.get_next_node() returns None, that value None is assigned in line 4 to current_node, which terminates the while loop.


What do you mean by the pointer?


… because when you get to the end, as noted above, that final node is None, and you will see
AttributeError: 'NoneType' object has no attribute 'get_value'

4 Likes

hello folks. please help me out here coz I have been struggling with this code for a long while now.

`
class Node:
def init(self, value, next_node=None):
self.value = value
self.next_node = next_node

def get_value(self):
return self.value

def get_next_node(self):
return self.next_node

def set_next_node(self, next_node):
self.next_node = next_node

Our LinkedList class

class LinkedList:
def init(self, value=None):
self.head_node = Node(value)

def get_head_node(self):
return self.head_node

Add your insert_beginning and stringify_list methods below:

def insert_beginning(self, new_value):
new_node = Node(new_value)
new_node.set_next_node(self.head_node)
self.head_node = new_node

def stringify_list(self):
string_list = “”
current_node = self.get_head_node()
while current_node:
if current_node.get_value() != None:
string_list += str(current_node.get_value()) + “\n”
current_node = current_node.get_next_node()
return string_list

Test your code by uncommenting the statements below - did your list print to the terminal?

ll = LinkedList(5)
ll.insert_beginning(70)
ll.insert_beginning(5675)
ll.insert_beginning(90)
print(ll.stringify_list())
`

the confusing part is new_node.set_next_node(self.head_node) self.head_node = new_node . what is it that actually happened here. ‘new_node’ is an object of the node class. and I believe “new_value” passed when creating this object points to the “value” parameter of the Node class. and when we used “.set_next_node” method on the “new_node”, the “self.head_node” we passed as arguement represents what? is it the value of the Node class or that of the LinkedIn class.

please use the calls
"
ll = LinkedList(5)
ll.insert_beginning(70)
ll.insert_beginning(5675)
ll.insert_beginning(90)
print(ll.stringify_list()) " made on these object to explain. At what point did the arguement “5” passed become “value” of Node class and at which point did the other ones starting from “70” become “next_node” of the Node class. please help explain these things so that I can visualize them better. thanks famz for your help.

1 Like

Hello dear, I love the explanations you gave here. but I just need some clarifications here. what exactly does " current_node = current_node.next_node" do here. I mean what exactly gets updasted to as “current_node” .? In the exercise, “insert_beginning” was used on “70, 5675, 90”. 90 was the last one and at that point, I believed “head_node” is now = (90, next_node), where the next_node is (5675, 70). so is current_node.next_node pointing to this particular (5675, 70) ? let me use the function so you understand better my confusion.

ll = LinkedList(5)
which means head_node is = (5, none)

insert_beginning(70)   
new_node = Node(70)
new_node.set_next_node(5, node)
self.head_node = (70, (5, none))

insert_beginning(5675)   
new_node = Node(5675)
new_node.set_next_node(70, 5))
self.head_node = (5675, (70, 5))

insert_beginning(90)
new_node = Node(90)
new_node.set_next_node(5675, 70)
self.head_node = (90, (5675, 70))

so using the stringify_list method, which next_node are they referring to when they called current_node = current_node.next_node ?

please help me solve this so I can visualize it better. I have been stuck here for weeks now. thanks.

Ehm. Doesn’t the expression say that?
current_node.next_node
If you have nodes numbered 0, 1, 2, … then the node after 347 is 348

I’d also argue that you should be able to execute it in year head or with pen and paper and observe what it makes you do. The code is the answer to your question, it says what it does, that’s what code is.

Or, if you’re going to avoid reading it, then consider what action is being implemented and how that would have to be done.
If you draw a small list on paper then you can do the operation manually and observe yourself.
(and if you don’t know how to draw a list then that’s the real problem, you would then want to first figure out what a list at all is before you start thinking about how to do operations on it)

it is okay. I only asked because I was confused. your answer did not help in any way. But I will continue to ask around. Thanks,.

Isn’t that what you’re asking though? “which node is the next node”

“the next node” is not a specific node, it’s the one that comes after the one you got it from

and if you repeatedly walk to the next node then you’ll have traveled several nodes

you can print it too, that’ll tell you specifically which one of your nodes it is.

linked lists can be executed on paper by drawing a circle for each node and having lines for links, you can follow the links to traverse the list, and you can move the links by crossing out/erasing and drawing new ones.

if you already know what your action should do then you already know … what it’s doing. or if you don’t, then figure that out before you start doing it with code, reasoning about the ideas doesn’t need to be in code it’ll only get in your way

thanks buddy… I really appreciate your response. you know sometimes, little codes can drive one crazy. The mystery has been solved. The truth was that I held complex things in my head, I just missed it at a point…and this “the next node” is not a specific node, it’s the one that comes after the one you got it from" helped me too.
Thanks again.

Thank you, that helped a lot!

After seeing your code I noticed I forgot to add a step to go to the next node, thus looping infinitely.

def stringify_list(self):
    string_list = ""
    current = self.get_head_node()
    while current:
      string_list += str(current.get_value()) + '\n'
      current = current.next_node
    return string_list  

worked for me

1 Like

I’ve got a question. Is there someone who could explain why 5 is not printed, only 90, 5675 and 70

If you mean that you’ve put a couple of values in a list, and some of them aren’t showing up when printing the list, that would be a bug.

As for why, that would be a matter of observing what operations you’re carrying out, which is a degree of control over your code that you need to have anyway.

Hey, Thanks.
This was a bug, I woke up today, ran 3 more times the same code, and it printed out all values. All good now.

The if statement is essential. Note that if a value is None, then it doesn’t get printed because there is no data in the Node. Give it a try by adding ll.insert_beginning(None) to the list of assignments. Put it between the other assignments so the result will stand out.

def stringify_list(self):
    string_list = ""
    current_node = self.get_head_node()
    while current_node:
      if current_node.get_value() != None:        # check against the value None
        string_list += str(current_node.get_value()) + "\n"
      current_node = current_node.get_next_node()
    return string_list

  

# Test your code by uncommenting the statements below - did your list print to the terminal?
ll = LinkedList(5)
ll.insert_beginning(70)
ll.insert_beginning(5675)
ll.insert_beginning(None)
ll.insert_beginning(90)

print(ll.stringify_list())

The exercise is located at: https://www.codecademy.com/paths/computer-science/tracks/linear-data-structures/modules/cspath-linked-lists/lessons/learn-linked-lists-python/exercises/linked-lists-python-list-ii

My question pertains to the way the While loop is written in the stringify_list function.

The entire code is below but the relevant section is here:

while cur_node:
     if cur_node.get_value() != None:
       string_list += str(cur_node.get_value()) + "\n"
       cur_node = cur_node.get_next_node()
   return string_list

Q1. What does “while cur_node” mean? How should this be read ? Is it saying “while cur_node” has a value that is not “None”?
Q2. Why do we not get the right answer when we write this section as follows? In this case all the values of in the Linkedlist do not get printed.

   while cur_node.get_value() != None:
       string_list += str(cur_node.get_value()) + "\n"
       cur_node = cur_node.get_next_node()
   return string_list
# THE FULL CODE
class Node:
  def __init__(self, value, next_node=None):
    self.value = value
    self.next_node = next_node
    
  def get_value(self):
    return self.value
  
  def get_next_node(self):
    return self.next_node
  
  def set_next_node(self, next_node):
    self.next_node = next_node

# Our LinkedList class
class LinkedList:
  def __init__(self, value=None):
    self.head_node = Node(value)
  
  def get_head_node(self):
    return self.head_node
  
# Add your insert_beginning and stringify_list methods below:
  def insert_beginning(self, new_value):
    new_node = Node(new_value)
    new_node.set_next_node(self.head_node)
    self.head_node = new_node
  
  def stringify_list(self):
   string_list = ""
   cur_node = self.get_head_node()
   while cur_node:
     if cur_node.get_value() != None:
       string_list += str(cur_node.get_value()) + "\n"
       cur_node = cur_node.get_next_node()
   return string_list

The while statement will run whilst the expression evaluates to True; like most logic statement in Python such as if the expression is effectively evaluated by bool(). So the loop runs as long as cur_node is True or evaluates to True: truth value testing. If you prefer, cur_node is not None is perfectly valid as well as closer to the way you actually described it with English and therefore more explicit.

It looks like you’re confusing the Node itself and its value(s). You probably shouldn’t be testing the value of the node as a method of stepping through your linked list; having a list with values like None, False or 0 is perfectly valid and should not prevent links. You test the node itself, not its values.

What the while loop does is that it loops an unknown amount of times until the condition is not met. In our case, we set the current_node equal to the value we returned from the get_head_node() method, which is also the value argument we passed into our Node class.

As we loop through our list, we add the value that we get for each node and put it in our string list.

Finally, after we have added the value to our string list, we can set the current node equal to the value of the next node.

In this exercise, the linked list has the following values after we instantiate the LinkedList class and then add new beginnings:
90
5675
70
5

What command do we use to print the values in this linked list all at once? Is it possible to do it without the stringify method?

As I understand it, the LinkedList is essentially just a collection of nodes. So can you see all the nodes in the LinkedList at once?

1 Like

My understanding is no, we cannot see all the values in a linked list at once, unless we create some functionality that goes through each node for us like we did in this lesson. That’s the nature of linked lists. You can only see the value of one node at a time, then follow its link to the next node.

If anyone is interested in further reading on nodes and linked lists, I found baseCS’s article “What’s a Linked List, Anyway?” (part 1) (part 2) to be very clear and informative.