Stacks and queues
What you'll learn:
- turn a list into a stack with
appendandpop; - build a queue on a
dequeand explain why a list'spop(0)is slow; - find a number in a sorted list with binary search and with
bisect; - put together a class from a dict, methods and your own exception.

Picture a stack of plates in a kitchen. A clean plate goes on top. When you need a plate, you take it from the top too—the very one that was put there last. The bottom plate comes up only after all the others are gone.
Programs often need the same order. The Undo button in an editor first undoes the latest action, then the one before it. What is saved later comes out sooner.
An ordinary list gives this order if you add and remove elements only at its end:
history = []
history.append("type")
history.append("bold")
history.append("delete")
print(history[-1]) # delete
last = history.pop()
print(last, history) # delete ['type', 'bold']Let's walk through the example line by line:
- Three
appendcalls put the actions"type","bold"and"delete"on the stackhistory. The last one ends up on top. history[-1]looks at the top plate and printsdeletewithout taking anything off.history.pop()takes the top value off and stores it inlast.- The last
printprintsdelete ['type', 'bold']: the first two actions are left in the list.
A stack on a list
A stack is a collection of values that you add to and remove from at one end only. That end is called the top. The value put on last is taken off first, like the top plate.
In a list, the top is its end. A stack needs three actions:
append(x)puts the valuexon top;pop()with no argument takes the value off the top and returns it;stack[-1]only looks at the top and does not change the stack.
No other elements move. So append and pop() are equally fast on a list of any length.
The loop while stack: takes values off until the stack is empty: an empty list is falsy. The values come out in the reverse of the order in which they were put on:
words = ["one", "two", "three"]
stack = []
for w in words:
stack.append(w)
out = []
while stack:
out.append(stack.pop())
print(out) # ['three', 'two', 'one']The words went onto the stack as one, two, three and came out the other way around. The first plate put down always ends up at the very bottom.
This is where the analogy stops. A real stack won't give up its middle plate, but a list has no such rule: stack[0] reads the bottom element. A stack is an agreement: the program itself decides to touch only the top.
That is why a stack suits tasks where whatever opened last must close first. Nested brackets in an expression work this way.
A queue on a deque
A queue works the other way around: the value that came first is taken first, as in a line at a checkout. A list's pop(0) also takes the first element, but slowly. After it, every remaining element moves one position to the left. In a list of a million elements, each call moves almost a million values.
For a queue, the collections module has the type deque. It is like a list, but it adds and removes values quickly at both ends. The line from collections import deque loads the single name deque from the module:
from collections import deque
line = deque(["Ann", "Bob"])
line.append("Kim")
first = line.popleft()
print(first, line) # Ann deque(['Bob', 'Kim'])
print(len(line), line[0]) # 2 BobLet's see what happens here:
deque(["Ann", "Bob"])creates a queue with"Ann"at the front.append("Kim")adds"Kim"at the end of the queue.popleft()takes a value off the start, that is, the left end, and returns"Ann".lenand reading by index work the same as for a list: two people are in line, andBobis first.
A deque has a pop() method too, and like a list's, it takes the last value.
Interviewers like to ask why a queue isn't built on a list. The answer: pop(0) shifts every remaining element, while a deque's popleft() takes the first element without any shifting.
Common mistake
A value is taken off an empty stack:
stack = []
stack.pop() # ✗IndexError: pop from empty listThere is nothing to take, and the program stops with an IndexError. popleft() on an empty deque raises an IndexError too. Before you take a value off, check that the collection is not empty—if stack: or while stack:, as in the loop above.
Key points
- A stack gives back first what was put on last; on a list, that is
appendandpop(). stack[-1]looks at the top without taking it off.- A queue gives back first what came first; it is built on a
dequewithappendandpopleft(). pop()andpopleft()on an empty collection raiseIndexError, so checkif stack:first.
Subscribe to take the course
The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.