A Question about Stack (Data Structure)

from node import Node

class Stack:
  def __init__(self, value = None):
    self.top_item = Node(value)

class Stack:
  def __init__(self):
    self.top_item = None

I am a beginner and learning stack for the first time. Above the two constructors seems to do the same thing. But I don’t quite get it.

What does it mean when you set a node to None?

And self.top_item is not even an instance of class Node. Why does it act like one?

Hi again,

This has to do with the concept of having optional paramaters

def some_function(required_A, required_B, optional_C = None):

It means that when you call the function, you only need to give A and B (and choose not to give C if you don’t need it).

The importance of this is that you don’t make a statement in the body of the function that says optional_C = None, because every time you call that function, C will be None even though you may need it to not be.

Notice the difference:

def some_function(required_A, required_B, optional_C = 0):
   result = required_A + required_B
   result += optional_C
   return result

some_function(1, 2)
# returns 3

some_function(1, 2, 3)
# returns 6
# without the optional parameter
def some_function(required_A, required_B):
   c = 0
   result = required_A + required_B
   result += c
   return result

some_function(1, 2)
# returns 3

some_function(1, 2, 3)
# throws an error

Why you need this in a stack is a challenge more about learning how stacks work.

Can you show them doing the same thing?

For example, can you push two values and then pop all values, using both of those, and get the same outcome?

push 3
push 5
while not empty:
    print pop

better yet, can you push None values to your stack and still have it behave correctly?

push None
push None
while not empty:
    print pop
1 Like

@ [cloud1080432534] I found it particularly useful to remember this later when it came to certain recursive calls.

The key point is you get more control over your variables.


On the URL above, if you click “get help” on the bottom right corner, then click “solution”, solution will be given.
In that solution constructor has “self.top_item = None” line. I changed it to “self.top_item = Node(value)” and included in the parameter" value = None". The outcome was the same.

what outcome, outcome of what?

maybe it’s a lack of measurement. if you do not measure, then both will have the same outcome: nothing

I proposed something that you can measure

The guideline directs me to delete # from comments below, and print out outcome on the console.

Yes I can understand the examples you have kindly given to me. But I have to ponder some time how your example is related to my question.

their code is judging emptiness by an internal counter (size) instead of looking at the structure

and if that’s done then you don’t need to define the (non-existing) top value at all since it would never be looked at

and no it doesn’t behave like a Node. it’s never used

Then I want to ask you this question. What class an instance “self.top_item” belong to?

Then I want to ask you this question. What class an instance “self.top_item” belong to?

variables don’t have types

conceptually you are using that variable to point to a linked list

a linked list is empty or a cell

you’d start with empty


and to prepend something you put it in a cell

cell(5, empty)

repeat for each prepend

cell(1, cell(3, cell(5, empty)))

to determine whether a linked list is empty, you compare it to empty

if mylist == empty

how you define empty is up to you so long as you can tell it apart from actual values

it would be nice if both cell and empty are instances of LinkedList, which you can achieve with inheritance, or perhaps by letting empty be a special case of cell, but you’re not, so you’re completely ignoring types and instead looking at what the values look like

but you’re ignoring that value so it’s completely irrelevant what it is, you could use any value, you’re using self.size to determine if there are more values … which is a bit bloated really, and is related to the artificial stack limit (there’s no reason for that limit)

@ionatan is being extremely helpful.

The idea is, a person is always going to have questions if they don’t try applying the concept practically.

He gave some examples of code to run that if you draw it out, will highlight for you what it is that you are asking.

Of course some things will feel unclear at first, but once you draw it out a lot of the questions will answer themselves (by the sheer necessity of the task). That’s why he gave you those particular examples to try out.

It’s a clever pedagogical tool. And if you can devise that kind of test with your own code in the future you will be able to problem solve unforeseen issues.

It doesn’t matter what empty looks like, because your size counter would be 0 and you would never look at it.

If you had no size counter, and instead used only the structure, then you would need to be able to tell apart a Node and empty. If you define empty as a Node, then you have a problem, because a Node is not empty, a Node is a value, and you have no value. If you use Node(None) then you just added None to your stack which was supposed to be empty.

Also, a stack is not a data structure that is different from linked list. A linked list is a stack. There are other structures that are also stacks. I feel like I have to say this, because, you did implement linked list, and then you implemented stack, but this stack is a linked list so you did the same thing again and called it something else.