A Menu-Driven Stack
Almost every practical file has this program. The five stack functions sit at the top. Below them, a loop shows a menu, reads the user's choice and calls the function that matches. It keeps going until the user picks Exit.
1The plan, before the code
isEmpty, push, pop, peek and display — exactly as in the last lesson.
stack = [] made once, above the loop, so it lasts the whole run.
while True: show the menu, read a choice, call a function; break on Exit.
2The program, and a real run
def isEmpty(stack):
if len(stack) == 0:
return True
else:
return False
def push(stack, item):
stack.append(item)
def pop(stack):
if isEmpty(stack):
print('Underflow')
return None
else:
return stack.pop()
def peek(stack):
if isEmpty(stack):
print('Stack is empty')
return None
else:
return stack[-1]
def display(stack):
if isEmpty(stack):
print('Stack is empty')
else:
for i in range(len(stack) - 1, -1, -1):
print(stack[i])
stack = []
while True:
print('1.Push 2.Pop 3.Peek 4.Display 5.Exit')
choice = input('Enter your choice: ')
if choice == '1':
item = int(input('Number to push: '))
push(stack, item)
elif choice == '2':
item = pop(stack)
if item is not None:
print('Popped', item)
elif choice == '3':
item = peek(stack)
if item is not None:
print('Top is', item)
elif choice == '4':
display(stack)
elif choice == '5':
print('Bye!')
break
else:
print('Please choose 1 to 5.')1.Push 2.Pop 3.Peek 4.Display 5.Exit Enter your choice: 1 Number to push: 10 1.Push 2.Pop 3.Peek 4.Display 5.Exit Enter your choice: 1 Number to push: 20 1.Push 2.Pop 3.Peek 4.Display 5.Exit Enter your choice: 1 Number to push: 30 1.Push 2.Pop 3.Peek 4.Display 5.Exit Enter your choice: 4 30 20 10 1.Push 2.Pop 3.Peek 4.Display 5.Exit Enter your choice: 3 Top is 30 1.Push 2.Pop 3.Peek 4.Display 5.Exit Enter your choice: 2 Popped 30 1.Push 2.Pop 3.Peek 4.Display 5.Exit Enter your choice: 2 Popped 20 1.Push 2.Pop 3.Peek 4.Display 5.Exit Enter your choice: 2 Popped 10 1.Push 2.Pop 3.Peek 4.Display 5.Exit Enter your choice: 2 Underflow 1.Push 2.Pop 3.Peek 4.Display 5.Exit Enter your choice: 7 Please choose 1 to 5. 1.Push 2.Pop 3.Peek 4.Display 5.Exit Enter your choice: 5 Bye!
Follow the run against the code. Three pushes, a display that prints 30 first, a peek that leaves 30 where it is, three pops that come out 30, 20, 10, a fourth pop that reports underflow, a wrong choice, and Exit.
stack = []Above the loop, so it is made once. Every round of the loop uses the same list.
while True:The loop has no natural end, because nobody knows how many choices the user will make. It runs until break.
if choice == '1':input() always hands back text, so the choice is compared with the text '1', in quotes.
if item is not None:pop() hands back None when it could not pop. Checking for that stops the program printing Popped None after the Underflow message.
breakThe only way out of the loop. Without it, choosing 5 would print Bye! and show the menu again.
else:Catches any choice that is not 1 to 5, so a typing mistake gets a message instead of silence.
3Mistake 1 — comparing the choice with a number
choice = input('Enter your choice: ')
if choice == 1:
print('Push chosen')
else:
print('Please choose 1 to 5.')Enter your choice: 1 Please choose 1 to 5.
The user typed 1 and was told to choose 1. choice holds the text '1', and the text '1' is never equal to the number 1. No error appears — every choice simply falls through to else. In the full menu program, that includes 5, so the loop can never end. Compare with '1', or convert first with int(input(...)).
4Mistake 2 — making the list inside the loop
def push(stack, item):
stack.append(item)
def display(stack):
if len(stack) == 0:
print('Stack is empty')
else:
for i in range(len(stack) - 1, -1, -1):
print(stack[i])
while True:
stack = []
print('1.Push 4.Display 5.Exit')
choice = input('Enter your choice: ')
if choice == '1':
item = int(input('Number to push: '))
push(stack, item)
elif choice == '4':
display(stack)
elif choice == '5':
break1.Push 4.Display 5.Exit Enter your choice: 1 Number to push: 10 1.Push 4.Display 5.Exit Enter your choice: 4 Stack is empty 1.Push 4.Display 5.Exit Enter your choice: 5
10 was pushed, and one round later the stack is empty. The line stack = [] runs at the start of every round, so each round starts with a fresh, empty list. Move it above while True: and the stack remembers.
5Why is not None, and not just if item:
stack = [0]
item = stack.pop()
if item:
print('Popped', item)
print('The if printed nothing, yet', item, 'was popped.')The if printed nothing, yet 0 was popped.
if item: treats 0 as false, so a stack holding a 0 would pop it without saying so. if item is not None: asks the question that is really meant: did pop() hand back an item at all?6Run it yourself
The same program, runnable. It asks for input as it goes — try popping an empty stack, and try a choice of 9.
7Recap
Inside the loop, the stack is emptied at the start of every round.
The loop ends only when the user chooses Exit.
input() hands back text. Text never equals a number.
Tells 'nothing was popped' apart from 'a 0 was popped'.
- 1
Add a sixth choice, 6. Size, that prints how many items are on the stack.
Hint · One more
elif, andlen(stack). - 2
Make the stack hold names instead of numbers.
Hint · Only one line changes: drop the
int()aroundinput(). - 3
Give the stack room for only 5 items, and print Overflow when a sixth push is tried.
Hint · Check
len(stack) == 5before theappend()inside push.
In the menu program, why is stack = [] written above while True: and not inside it?
choice = input('Enter your choice: ') and the user types 1. What is choice == 1?
What ends the while True: loop in the menu program?