Collections
Deque
Double-Ended Queue
Your text editor needs undo (stack) and your print queue needs first-come-first-served
(queue). Using a list for queue is slow - pop(0) is O(n). Deque gives you O(1)
operations on both ends.
Undo with a stack
Use deque as a stack for undo functionality.
from collections import deque
def main():
# Undo history using deque as stack
undo_history = deque()
current_text = ""
print("=== Text Editor with Undo ===\n")
# Perform actions (each saves state to undo stack)
current_text = perform_action(undo_history, current_text, "Hello")
current_text = perform_action(undo_history, current_text, " World")
current_text = perform_action(undo_history, current_text, "!")
# More editing actions
current_text = perform_action(undo_history, current_text, " How")
current_text = perform_action(undo_history, current_text, " are")
current_text = perform_action(undo_history, current_text, " you?")
print(f'Current text: "{current_text}"')
print(f"Undo stack size: {len(undo_history)}")
# Undo operations
print("\n=== Performing Undo ===")
current_text = undo(undo_history, current_text)
current_text = undo(undo_history, current_text)
print(f'\nAfter 2 undos: "{current_text}"')
# Undo more actions
current_text = undo(undo_history, current_text)
current_text = undo(undo_history, current_text)
print(f'After more undos: "{current_text}"')
def perform_action(history, current, addition):
history.append(current) # Save current state (push)
new_text = current + addition
print(f'Action: Add "{addition}" → "{new_text}"')
return new_text
def undo(history, current):
if history: # Check if not empty
previous = history.pop() # Get previous state
print(f'Undo: "{current}" → "{previous}"')
return previous
else:
print("Nothing to undo!")
return current
main()
main()
52main()53#@help stackundo_history ← deque([]), current_text ← (empty)
3#@var=default,moreUndos4def main():5 # Undo history using deque as stack #?stack6 undo_history→ deque([]) = deque()7 current_text→ (empty) = ""8 9 print("=== Text Editor with Undo ===\n")10 11 # Perform actions (each saves state to undo stack)12 current_text = perform_action(undo_historydeque([]), current_text(empty), "Hello")13 current_text = perform_action(undo_history, current_text, " World")output=== Text Editor with Undo ===history ← deque(['']), new_text ← Hello
pass 1 of 637def perform_action(historydeque([]), current(empty), additionHello):38 history→ deque(['']).append(current(empty)) # Save current state (push) #?append39 new_text→ Hello = current(empty) + additionHello40 print(f'Action: Add "{additionHello}" → "{new_textHello}"')41 return new_textHellooutputAction: Add "Hello" → "Hello"All 6 passes — pass 1 is the card above pass currentadditionhistorynew_text1 (empty) Hello deque([]) → deque(['']) Hello 2 Hello World deque(['']) → deque(['', 'Hello']) Hello World 3 Hello World ! deque(['', 'Hello']) → deque(['', 'Hello', 'Hello World']) Hello World! 4 Hello World! How deque(['', 'Hello', 'Hello World']) → deque(['', 'Hello', 'Hello World', 'Hello World!']) Hello World! How 5 Hello World! How are deque(['', 'Hello', 'Hello World', 'Hello World!']) → deque(['', 'Hello', 'Hello World', 'Hello World!', 'Hello World! How']) Hello World! How are 6 Hello World! How are you? deque(['', 'Hello', 'Hello World', 'Hello World!', 'Hello World! How']) → deque(['', 'Hello', 'Hello World', 'Hello World!', 'Hello World! How', 'Hello World! How are']) Hello World! How are you? undo_history ← deque(['']), current_text ← Hello
11# Perform actions (each saves state to undo stack)12current_text→ Hello = perform_action(undo_history→ deque(['']), current_text, "Hello")13current_text = perform_action(undo_historydeque(['']), current_textHello, " World")14current_text = perform_action(undo_history, current_text, "!")undo_history ← deque(['', 'Hello']), current_text ← Hello World
12current_text = perform_action(undo_history, current_text, "Hello")13current_text→ Hello World = perform_action(undo_history→ deque(['', 'Hello']), current_text, " World")14current_text = perform_action(undo_historydeque(['', 'Hello']), current_textHello World, "!")undo_history ← deque(['', 'Hello', 'Hello World']), current_text ← Hello World!
13current_text = perform_action(undo_history, current_text, " World")14current_text→ Hello World! = perform_action(undo_history→ deque(['', 'Hello', 'Hello World']), current_text, "!")1516# More editing actions17current_text = perform_action(undo_historydeque(['', 'Hello', 'Hello World']), current_textHello World!, " How") #@var=_,!18current_text = perform_action(undo_history, current_text, " are") #@var=_,!undo_history ← deque(['', 'Hello', 'Hello World', 'Hello World!'])
16# More editing actions17current_text→ Hello World! How = perform_action(undo_history→ deque(['', 'Hello', 'Hello World', 'Hello World!']), current_text, " How") #@var=_,!18current_text = perform_action(undo_historydeque(['', 'Hello', 'Hello World', 'Hello World!']), current_textHello World! How, " are") #@var=_,!19current_text = perform_action(undo_history, current_text, " you?") #@var=_,!undo_history ← deque(['', 'Hello', 'Hello World', 'Hello World!', 'Hello World! How'])
17current_text = perform_action(undo_history, current_text, " How") #@var=_,!18current_text→ Hello World! How are = perform_action(undo_history→ deque(['', 'Hello', 'Hello World', 'Hello World!', 'Hello World! How']), current_text, " are") #@var=_,!19current_text = perform_action(undo_historydeque(['', 'Hello', 'Hello World', 'Hello World!', 'Hello World! How']), current_textHello World! How are, " you?") #@var=_,!undo_history ← deque(['', 'Hello', 'Hello World', 'Hello World!', 'Hello World! How', 'Hello World! How are'])
18current_text = perform_action(undo_history, current_text, " are") #@var=_,!19current_text→ Hello World! How are you? = perform_action(undo_history→ deque(['', 'Hello', 'Hello World', 'Hello World!', 'Hello World! How', 'Hello World! How are']), current_text, " you?") #@var=_,!2021print(f'Current text: "{current_textHello World! How are you?}"')22print(f"Undo stack size: {len(undo_historydeque(['', 'Hello', 'Hello World', 'Hello World!', 'Hello World! How', 'Hello World! How are']))}")2324# Undo operations #?undo25print("\n=== Performing Undo ===")2627current_text = undo(undo_historydeque(['', 'Hello', 'Hello World', 'Hello World!', 'Hello World! How', 'Hello World! How are']), current_textHello World! How are you?)28current_text = undo(undo_history, current_text)outputCurrent text: "Hello World! How are you?" Undo stack size: 6 === Performing Undo ===def undo(history, current):
pass 1 of 443def undo(historydeque(['', 'Hello', 'Hello World', 'Hello World!', 'Hello World! How', 'Hello World! How are']), currentHello World! How are you?):44 if history: # Check if not empty #?empty45 previous = history.pop() # Get previous stateAll 4 passes — pass 1 is the card above pass historycurrent1 deque(['', 'Hello', 'Hello World', 'Hello World!', 'Hello World! How', 'Hello World! How are']) Hello World! How are you? 2 deque(['', 'Hello', 'Hello World', 'Hello World!', 'Hello World! How']) Hello World! How are 3 deque(['', 'Hello', 'Hello World', 'Hello World!']) Hello World! How 4 deque(['', 'Hello', 'Hello World']) Hello World! history ← deque(['', 'Hello', 'Hello World', 'Hello World!', 'Hello World! How'])
pass 1 of 443def undo(history, current):44 if historydeque(['', 'Hello', 'Hello World', 'Hello World!', 'Hello World! How', 'Hello World! How are']): # Check if not empty #?empty45 previous→ Hello World! How are = history→ deque(['', 'Hello', 'Hello World', 'Hello World!', 'Hello World! How']).pop() # Get previous state46 print(f'Undo: "{currentHello World! How are you?}" → "{previousHello World! How are}"')47 return previousHello World! How are48 else:outputUndo: "Hello World! How are you?" → "Hello World! How are"All 4 passes — pass 1 is the card above pass currenthistoryprevious1 Hello World! How are you? deque(['', 'Hello', 'Hello World', 'Hello World!', 'Hello World! How', 'Hello World! How are']) → deque(['', 'Hello', 'Hello World', 'Hello World!', 'Hello World! How']) Hello World! How are 2 Hello World! How are deque(['', 'Hello', 'Hello World', 'Hello World!', 'Hello World! How']) → deque(['', 'Hello', 'Hello World', 'Hello World!']) Hello World! How 3 Hello World! How deque(['', 'Hello', 'Hello World', 'Hello World!']) → deque(['', 'Hello', 'Hello World']) Hello World! 4 Hello World! deque(['', 'Hello', 'Hello World']) → deque(['', 'Hello']) Hello World undo_history ← deque(['', 'Hello', 'Hello World', 'Hello World!', 'Hello World! How'])
27current_text→ Hello World! How are = undo(undo_history→ deque(['', 'Hello', 'Hello World', 'Hello World!', 'Hello World! How']), current_text)28current_text = undo(undo_historydeque(['', 'Hello', 'Hello World', 'Hello World!', 'Hello World! How']), current_textHello World! How are)undo_history ← deque(['', 'Hello', 'Hello World', 'Hello World!'])
27current_text = undo(undo_history, current_text)28current_text→ Hello World! How = undo(undo_history→ deque(['', 'Hello', 'Hello World', 'Hello World!']), current_text)2930print(f'\nAfter 2 undos: "{current_textHello World! How}"')3132# Undo more actions33current_text = undo(undo_historydeque(['', 'Hello', 'Hello World', 'Hello World!']), current_textHello World! How) #@var=_,!34current_text = undo(undo_history, current_text) #@var=_,!output After 2 undos: "Hello World! How"undo_history ← deque(['', 'Hello', 'Hello World']), current_text ← Hello World!
32# Undo more actions33current_text→ Hello World! = undo(undo_history→ deque(['', 'Hello', 'Hello World']), current_text) #@var=_,!34current_text = undo(undo_historydeque(['', 'Hello', 'Hello World']), current_textHello World!) #@var=_,!35print(f'After more undos: "{current_text}"') #@var=_,!undo_history ← deque(['', 'Hello']), current_text ← Hello World
33current_text = undo(undo_history, current_text) #@var=_,!34current_text→ Hello World = undo(undo_history→ deque(['', 'Hello']), current_text) #@var=_,!35print(f'After more undos: "{current_textHello World}"') #@var=_,!outputAfter more undos: "Hello World"main()
52main()53#@help stack
append() pushes, pop() pops from right. Last in, first out.
Process tasks in order
Use deque as a queue for FIFO processing.
from collections import deque
def main():
# Task queue - process in order received
task_queue = deque()
print("=== Task Queue System ===\n")
# Add tasks to queue
print("Adding tasks:")
task_queue.append("Process order #101")
print(" Added: Process order #101")
task_queue.append("Send confirmation email")
print(" Added: Send confirmation email")
task_queue.append("Update inventory")
print(" Added: Update inventory")
# Add more tasks
task_queue.append("Generate report")
task_queue.append("Notify warehouse")
task_queue.append("Archive order")
print(" Added 3 more tasks...")
print(f"\nQueue: {list(task_queue)}")
print(f"Tasks pending: {len(task_queue)}")
# Process tasks in order
print("\n=== Processing Tasks ===")
task_num = 1
while task_queue:
task = task_queue.popleft() # Remove from FRONT
print(f"{task_num}. {task} ✓")
task_num += 1
print("\n=== All tasks completed! ===")
print(f"Queue empty: {len(task_queue) == 0}")
main()
main()
42main()43#@help queuetask_queue ← deque([]), task_num ← 1
3#@var=default,moreTasks4def main():5 # Task queue - process in order received #?queue6 task_queue→ deque([]) = deque()7 8 print("=== Task Queue System ===\n")9 10 # Add tasks to queue #?add11 print("Adding tasks:")12 task_queue→ deque(['Process order #101']).append("Process order #101")13 print(" Added: Process order #101")14 15 task_queue→ deque(['Process order #101', 'Send confirmation email']).append("Send confirmation email")16 print(" Added: Send confirmation email")17 18 task_queue→ deque(['Process order #101', 'Send confirmation email', 'Update inventory']).append("Update inventory")19 print(" Added: Update inventory")20 21 # Add more tasks22 task_queue→ deque(['Process order #101', 'Send confirmation email', 'Update inventory', 'Generate report']).append("Generate report") #@var=_,!23 task_queue→ deque(['Process order #101', 'Send confirmation email', 'Update inventory', 'Generate report', 'Notify warehouse']).append("Notify warehouse") #@var=_,!24 task_queue→ deque(['Process order #101', 'Send confirmation email', 'Update inventory', 'Generate report', 'Notify warehouse', 'Archive order']).append("Archive order") #@var=_,!25 print(" Added 3 more tasks...") #@var=_,!26 27 print(f"\nQueue: {list(task_queuedeque(['Process order #101', 'Send confirmation email', 'Update inventory', 'Generate report', 'Notify warehouse', 'Archive order']))}")28 print(f"Tasks pending: {len(task_queuedeque(['Process order #101', 'Send confirmation email', 'Update inventory', 'Generate report', 'Notify warehouse', 'Archive order']))}")29 30 # Process tasks in order #?process31 print("\n=== Processing Tasks ===")32 33 task_num→ 1 = 134 while task_queue:output=== Task Queue System === Adding tasks: Added: Process order #101 Added: Send confirmation email Added: Update inventory Added 3 more tasks... Queue: ['Process order #101', 'Send confirmation email', 'Update inventory', 'Generate report', 'Notify warehouse', 'Archive order'] Tasks pending: 6 === Processing Tasks ===task_queue ← deque(['Send confirmation email', 'Update inventory', 'Generate report', 'Notify warehouse', 'Archive order'])
pass 1 of 633task_num = 134while task_queuedeque(['Process order #101', 'Send confirmation email', 'Update inventory', 'Generate report', 'Notify warehouse', 'Archive order']):35 task→ Process order #101 = task_queue→ deque(['Send confirmation email', 'Update inventory', 'Generate report', 'Notify warehouse', 'Archive order']).popleft() # Remove from FRONT36 print(f"{task_num1}. {taskProcess order #101} ✓")37 task_num→ 2 += 1output1. Process order #101 ✓All 6 passes — pass 1 is the card above pass task_queuetasktask_num1 deque(['Process order #101', 'Send confirmation email', 'Update inventory', 'Generate report', 'Notify warehouse', 'Archive order']) → deque(['Send confirmation email', 'Update inventory', 'Generate report', 'Notify warehouse', 'Archive order']) Process order #101 1 → 2 2 deque(['Send confirmation email', 'Update inventory', 'Generate report', 'Notify warehouse', 'Archive order']) → deque(['Update inventory', 'Generate report', 'Notify warehouse', 'Archive order']) Send confirmation email 2 → 3 3 deque(['Update inventory', 'Generate report', 'Notify warehouse', 'Archive order']) → deque(['Generate report', 'Notify warehouse', 'Archive order']) Update inventory 3 → 4 4 deque(['Generate report', 'Notify warehouse', 'Archive order']) → deque(['Notify warehouse', 'Archive order']) Generate report 4 → 5 5 deque(['Notify warehouse', 'Archive order']) → deque(['Archive order']) Notify warehouse 5 → 6 6 deque(['Archive order']) → deque([]) Archive order 6 → 7 print(f"Queue empty: {len(task_queue) == 0}")
39print("\n=== All tasks completed! ===")40print(f"Queue empty: {len(task_queuedeque([])) == 0}")output === All tasks completed! === Queue empty: Truemain()
42main()43#@help queue
append() adds to right, popleft() removes from left. First in, first out.
Work with both ends
Add and remove from either end.
from collections import deque
def main():
# Deque allows operations on both ends
d = deque()
print("=== Adding to Both Ends ===")
# Add to right
d.append(2)
print(f"append(2): {list(d)}")
d.append(3)
print(f"append(3): {list(d)}")
# Add to left
d.appendleft(1)
print(f"appendleft(1): {list(d)}")
d.appendleft(0)
print(f"appendleft(0): {list(d)}")
# Access without removing
print("\n=== Access Elements ===")
print(f"d[0] (leftmost): {d[0]}")
print(f"d[-1] (rightmost): {d[-1]}")
print(f"d[2] (index 2): {d[2]}")
# Remove from both ends
print("\n=== Removing from Both Ends ===")
print(f"Current: {list(d)}")
left = d.popleft()
print(f"popleft() → {left}, deque now: {list(d)}")
right = d.pop()
print(f"pop() → {right}, deque now: {list(d)}")
# Practical: Palindrome check
print("\n=== Palindrome Check ===")
def is_palindrome(s):
# Remove non-letters and lowercase
chars = deque(c.lower() for c in s if c.isalpha())
while len(chars) > 1:
if chars.popleft() != chars.pop():
return False
return True
test_words = ["radar", "hello", "A man a plan a canal Panama"]
for word in test_words:
result = "✓ Palindrome" if is_palindrome(word) else "✗ Not palindrome"
print(f'"{word}" → {result}')
main()
main()
56main()57#@help bothd ← deque([]), left ← 0, right ← 3, test_words ← ['radar', 'hello', 'A man a plan a canal Panama']
3def main():4 # Deque allows operations on both ends #?both5 d→ deque([]) = deque()6 7 print("=== Adding to Both Ends ===")8 9 # Add to right10 d→ deque([2]).append(2)11 print(f"append(2): {list(ddeque([2]))}")12 13 d→ deque([2, 3]).append(3)14 print(f"append(3): {list(ddeque([2, 3]))}")15 16 # Add to left17 d→ deque([1, 2, 3]).appendleft(1)18 print(f"appendleft(1): {list(ddeque([1, 2, 3]))}")19 20 d→ deque([0, 1, 2, 3]).appendleft(0)21 print(f"appendleft(0): {list(ddeque([0, 1, 2, 3]))}")22 23 # Access without removing #?access24 print("\n=== Access Elements ===")25 print(f"d[0] (leftmost): {d[0]0}")26 print(f"d[-1] (rightmost): {d[-1]3}")27 print(f"d[2] (index 2): {d[2]2}")28 29 # Remove from both ends #?remove30 print("\n=== Removing from Both Ends ===")31 print(f"Current: {list(ddeque([0, 1, 2, 3]))}")32 33 left→ 0 = d→ deque([1, 2, 3]).popleft()34 print(f"popleft() → {left0}, deque now: {list(ddeque([1, 2, 3]))}")35 36 right→ 3 = d→ deque([1, 2]).pop()37 print(f"pop() → {right3}, deque now: {list(ddeque([1, 2]))}")38 39 # Practical: Palindrome check #?palindrome40 print("\n=== Palindrome Check ===")41 42 def is_palindrome(s):43 # Remove non-letters and lowercase44 chars = deque(c.lower() for c in s if c.isalpha())45 46 while len(chars) > 1:47 if chars.popleft() != chars.pop():48 return False49 return True50 51 test_words→ ['radar', 'hello', 'A man a plan a canal Panama'] = ["radar", "hello", "A man a plan a canal Panama"]52 for word in test_words:output=== Adding to Both Ends === append(2): [2] append(3): [2, 3] appendleft(1): [1, 2, 3] appendleft(0): [0, 1, 2, 3] === Access Elements === d[0] (leftmost): 0 d[-1] (rightmost): 3 d[2] (index 2): 2 === Removing from Both Ends === Current: [0, 1, 2, 3] popleft() → 0, deque now: [1, 2, 3] pop() → 3, deque now: [1, 2] === Palindrome Check ===for word in test_words:
pass 1 of 351test_words = ["radar", "hello", "A man a plan a canal Panama"]52for wordradar in test_words['radar', 'hello', 'A man a plan a canal Panama']:53 result = "✓ Palindrome" if is_palindrome(wordradar) else "✗ Not palindrome"54 print(f'"{word}" → {result}')All 3 passes — pass 1 is the card above pass wordchars1 radar — 2 hello deque(['e', 'l', 'l']) 3 A man a plan a canal Panama — chars ← deque(['r', 'a', 'd', 'a', 'r'])
pass 1 of 342def is_palindrome(sradar):43 # Remove non-letters and lowercase44 chars→ deque(['r', 'a', 'd', 'a', 'r']) = deque(c.lower() for c in sradar if c.isalpha())All 3 passes — pass 1 is the card above pass schars1 radar deque(['r', 'a', 'd', 'a', 'r']) 2 hello deque(['h', 'e', 'l', 'l', 'o']) 3 A man a plan a canal Panama deque(['a', 'm', 'a', 'n', 'a', 'p', 'l', 'a', 'n', 'a', 'c', 'a', 'n', 'a', 'l', 'p', 'a', 'n', 'a', 'm', 'a']) while len(chars) > 1:
pass 1 of 1346while len(charsdeque(['r', 'a', 'd', 'a', 'r'])) > 1:47 if chars.popleft() != chars.pop():48 return False13 passes — pass 1 is the card above pass chars1 deque(['r', 'a', 'd', 'a', 'r']) 2 deque(['a', 'd', 'a']) 3 deque(['h', 'e', 'l', 'l', 'o']) 4 deque(['a', 'm', 'a', 'n', 'a', 'p', 'l', 'a', 'n', 'a', 'c', 'a', 'n', 'a', 'l', 'p', 'a', 'n', 'a', 'm', 'a']) 5 deque(['m', 'a', 'n', 'a', 'p', 'l', 'a', 'n', 'a', 'c', 'a', 'n', 'a', 'l', 'p', 'a', 'n', 'a', 'm']) 6 deque(['a', 'n', 'a', 'p', 'l', 'a', 'n', 'a', 'c', 'a', 'n', 'a', 'l', 'p', 'a', 'n', 'a']) 7 deque(['n', 'a', 'p', 'l', 'a', 'n', 'a', 'c', 'a', 'n', 'a', 'l', 'p', 'a', 'n']) 8 deque(['a', 'p', 'l', 'a', 'n', 'a', 'c', 'a', 'n', 'a', 'l', 'p', 'a']) 9 deque(['p', 'l', 'a', 'n', 'a', 'c', 'a', 'n', 'a', 'l', 'p']) ⋯ 2 more passes ⋯ 12 deque(['n', 'a', 'c', 'a', 'n']) 13 deque(['a', 'c', 'a']) return True
48 return False49return Trueresult ← ✓ Palindrome
52for word in test_words:53 result→ ✓ Palindrome = "✓ Palindrome" if is_palindrome(wordradar) else "✗ Not palindrome"54 print(f'"{wordradar}" → {result✓ Palindrome}')output"radar" → ✓ Palindromeif chars.popleft() != chars.pop():
46while len(chars) > 1:47 if charsdeque(['e', 'l', 'l']).popleft() != chars.pop():48 return False49return Trueresult ← ✗ Not palindrome
52for word in test_words:53 result→ ✗ Not palindrome = "✓ Palindrome" if is_palindrome(wordhello) else "✗ Not palindrome"54 print(f'"{wordhello}" → {result✗ Not palindrome}')output"hello" → ✗ Not palindromereturn True
48 return False49return Trueresult ← ✓ Palindrome
52for word in test_words:53 result→ ✓ Palindrome = "✓ Palindrome" if is_palindrome(wordA man a plan a canal Panama) else "✗ Not palindrome"54 print(f'"{wordA man a plan a canal Panama}" → {result✓ Palindrome}')output"A man a plan a canal Panama" → ✓ Palindromemain()
56main()57#@help both
appendleft() adds to left, pop() removes from right. Full flexibility.
Sliding window with maxlen
Keep only the N most recent items.
from collections import deque
def main():
# Deque with maxlen - automatic sliding window
recent_temps = deque(maxlen=5)
print("=== Weather Station (Last 5 Readings) ===\n")
# Simulate temperature readings
temperatures = [72, 74, 71, 75, 78, 80, 76, 73, 70, 68]
for temp in temperatures:
recent_temps.append(temp) # Old items auto-removed!
avg = sum(recent_temps) / len(recent_temps)
print(f"Reading: {temp}°F | Recent: {list(recent_temps)} | Avg: {avg:.1f}°F")
print(f"\nFinal window: {list(recent_temps)}")
print(f"maxlen is: {recent_temps.maxlen}")
# Browser history with limit
print("\n=== Browser History (Max 3 pages) ===")
history = deque(maxlen=3)
pages = ["google.com", "github.com", "python.org", "stackoverflow.com", "docs.python.org"]
for page in pages:
history.append(page)
print(f"Visited {page}")
print(f" History: {list(history)}")
# Stock price moving average
print("\n=== Stock Moving Average ===")
window = deque(maxlen=3)
prices = [100, 102, 101, 105, 107, 103, 108, 110]
print("Price\tWindow\t\t\t3-day Avg")
print("-" * 45)
for price in prices:
window.append(price)
if len(window) == window.maxlen:
avg = sum(window) / len(window)
print(f"${price}\t{list(window)}\t\t${avg:.2f}")
else:
print(f"${price}\t{list(window)}\t\t(building window)")
main()
from collections import deque
def main():
# Deque with maxlen - automatic sliding window
recent_temps = 3
print("=== Weather Station (Last 5 Readings) ===\n")
# Simulate temperature readings
temperatures = [72, 74, 71, 75, 78, 80, 76, 73, 70, 68]
for temp in temperatures:
recent_temps.append(temp) # Old items auto-removed!
avg = sum(recent_temps) / len(recent_temps)
print(f"Reading: {temp}°F | Recent: {list(recent_temps)} | Avg: {avg:.1f}°F")
print(f"\nFinal window: {list(recent_temps)}")
print(f"maxlen is: {recent_temps.maxlen}")
# Browser history with limit
print("\n=== Browser History (Max 3 pages) ===")
history = deque(maxlen=3)
pages = ["google.com", "github.com", "python.org", "stackoverflow.com", "docs.python.org"]
for page in pages:
history.append(page)
print(f"Visited {page}")
print(f" History: {list(history)}")
# Stock price moving average
print("\n=== Stock Moving Average ===")
window = deque(maxlen=3)
prices = [100, 102, 101, 105, 107, 103, 108, 110]
print("Price\tWindow\t\t\t3-day Avg")
print("-" * 45)
for price in prices:
window.append(price)
if len(window) == window.maxlen:
avg = sum(window) / len(window)
print(f"${price}\t{list(window)}\t\t${avg:.2f}")
else:
print(f"${price}\t{list(window)}\t\t(building window)")
main()
main()
48main()49#@help maxlenrecent_temps ← deque([], maxlen=5), temperatures ← [72, 74, 71, 75, 78, 80, 76, 73, 70, 68]
3#@var=default,smaller4def main():5 # Deque with maxlen - automatic sliding window #?maxlen6 recent_temps→ deque([], maxlen=5) = deque(maxlen=5) #@var=_,37 8 print("=== Weather Station (Last 5 Readings) ===\n") #@var=_,Last 3 Readings9 10 # Simulate temperature readings11 temperatures→ [72, 74, 71, 75, 78, 80, 76, 73, 70, 68] = [72, 74, 71, 75, 78, 80, 76, 73, 70, 68]output=== Weather Station (Last 5 Readings) ===recent_temps ← deque([72], maxlen=5), avg ← 72.0
pass 1 of 1013for temp72 in temperatures[72, 74, 71, 75, 78, 80, 76, 73, 70, 68]:14 recent_temps→ deque([72], maxlen=5).append(temp72) # Old items auto-removed!15 avg→ 72.0 = sum(recent_tempsdeque([72], maxlen=5)) / len(recent_temps)16 print(f"Reading: {temp72}°F | Recent: {list(recent_tempsdeque([72], maxlen=5))} | Avg: {avg72.0:.1f}°F")outputReading: 72°F | Recent: [72] | Avg: 72.0°FAll 10 passes — pass 1 is the card above pass temprecent_tempsavg1 72 deque([], maxlen=5) → deque([72], maxlen=5) 72.0 2 74 deque([72], maxlen=5) → deque([72, 74], maxlen=5) 73.0 3 71 deque([72, 74], maxlen=5) → deque([72, 74, 71], maxlen=5) 72.33333333333333 4 75 deque([72, 74, 71], maxlen=5) → deque([72, 74, 71, 75], maxlen=5) 73.0 5 78 deque([72, 74, 71, 75], maxlen=5) → deque([72, 74, 71, 75, 78], maxlen=5) 74.0 6 80 deque([72, 74, 71, 75, 78], maxlen=5) → deque([74, 71, 75, 78, 80], maxlen=5) 75.6 7 76 deque([74, 71, 75, 78, 80], maxlen=5) → deque([71, 75, 78, 80, 76], maxlen=5) 76.0 8 73 deque([71, 75, 78, 80, 76], maxlen=5) → deque([75, 78, 80, 76, 73], maxlen=5) 76.4 9 70 deque([75, 78, 80, 76, 73], maxlen=5) → deque([78, 80, 76, 73, 70], maxlen=5) 75.4 10 68 deque([78, 80, 76, 73, 70], maxlen=5) → deque([80, 76, 73, 70, 68], maxlen=5) 73.4 history ← deque([], maxlen=3), pages ← ['google.com', 'github.com', 'python.org', 'stackoverflow.com', 'docs.python.org']
18print(f"\nFinal window: {list(recent_tempsdeque([80, 76, 73, 70, 68], maxlen=5))}")19print(f"maxlen is: {recent_temps.maxlen5}")2021# Browser history with limit #?history22print("\n=== Browser History (Max 3 pages) ===")23history→ deque([], maxlen=3) = deque(maxlen=3)2425pages→ ['google.com', 'github.com', 'python.org', 'stackoverflow.com', 'docs.python.org'] = ["google.com", "github.com", "python.org", "stackoverflow.com", "docs.python.org"]output Final window: [80, 76, 73, 70, 68] maxlen is: 5 === Browser History (Max 3 pages) ===history ← deque(['google.com'], maxlen=3)
pass 1 of 527for pagegoogle.com in pages['google.com', 'github.com', 'python.org', 'stackoverflow.com', 'docs.python.org']:28 history→ deque(['google.com'], maxlen=3).append(pagegoogle.com)29 print(f"Visited {pagegoogle.com}")30 print(f" History: {list(historydeque(['google.com'], maxlen=3))}")outputVisited google.com History: ['google.com']All 5 passes — pass 1 is the card above pass pagehistory1 google.com deque([], maxlen=3) → deque(['google.com'], maxlen=3) 2 github.com deque(['google.com'], maxlen=3) → deque(['google.com', 'github.com'], maxlen=3) 3 python.org deque(['google.com', 'github.com'], maxlen=3) → deque(['google.com', 'github.com', 'python.org'], maxlen=3) 4 stackoverflow.com deque(['google.com', 'github.com', 'python.org'], maxlen=3) → deque(['github.com', 'python.org', 'stackoverflow.com'], maxlen=3) 5 docs.python.org deque(['github.com', 'python.org', 'stackoverflow.com'], maxlen=3) → deque(['python.org', 'stackoverflow.com', 'docs.python.org'], maxlen=3) window ← deque([], maxlen=3), prices ← [100, 102, 101, 105, 107, 103, 108, 110]
32# Stock price moving average #?moving33print("\n=== Stock Moving Average ===")34window→ deque([], maxlen=3) = deque(maxlen=3)35prices→ [100, 102, 101, 105, 107, 103, 108, 110] = [100, 102, 101, 105, 107, 103, 108, 110]3637print("Price\tWindow\t\t\t3-day Avg")38print("-" * 45)output === Stock Moving Average === Price Window 3-day Avg ---------------------------------------------window ← deque([100], maxlen=3)
pass 1 of 840for price100 in prices[100, 102, 101, 105, 107, 103, 108, 110]:41 window→ deque([100], maxlen=3).append(price100)42 if len(window) == window.maxlen:All 8 passes — pass 1 is the card above pass pricewindow1 100 deque([], maxlen=3) → deque([100], maxlen=3) 2 102 deque([100], maxlen=3) → deque([100, 102], maxlen=3) 3 101 deque([100, 102], maxlen=3) → deque([100, 102, 101], maxlen=3) 4 105 deque([100, 102, 101], maxlen=3) → deque([102, 101, 105], maxlen=3) 5 107 deque([102, 101, 105], maxlen=3) → deque([101, 105, 107], maxlen=3) 6 103 deque([101, 105, 107], maxlen=3) → deque([105, 107, 103], maxlen=3) 7 108 deque([105, 107, 103], maxlen=3) → deque([107, 103, 108], maxlen=3) 8 110 deque([107, 103, 108], maxlen=3) → deque([103, 108, 110], maxlen=3) else:
pass 1 of 243 avg = sum(window) / len(window)44 print(f"${price}\t{list(window)}\t\t${avg:.2f}")45else:46 print(f"${price100}\t{list(windowdeque([100], maxlen=3))}\t\t(building window)")output$100 [100] (building window)else:
pass 2 of 243 avg = sum(window) / len(window)44 print(f"${price}\t{list(window)}\t\t${avg:.2f}")45else:46 print(f"${price102}\t{list(windowdeque([100, 102], maxlen=3))}\t\t(building window)")output$102 [100, 102] (building window)avg ← 101.0
pass 1 of 641window.append(price)42if len(windowdeque([100, 102, 101], maxlen=3)) == window.maxlen3:43 avg→ 101.0 = sum(windowdeque([100, 102, 101], maxlen=3)) / len(window)44 print(f"${price101}\t{list(windowdeque([100, 102, 101], maxlen=3))}\t\t${avg101.0:.2f}")45else:output$101 [100, 102, 101] $101.00All 6 passes — pass 1 is the card above pass windowpriceavg1 deque([100, 102, 101], maxlen=3) 101 101.0 2 deque([102, 101, 105], maxlen=3) 105 102.66666666666667 3 deque([101, 105, 107], maxlen=3) 107 104.33333333333333 4 deque([105, 107, 103], maxlen=3) 103 105.0 5 deque([107, 103, 108], maxlen=3) 108 106.0 6 deque([103, 108, 110], maxlen=3) 110 107.0 main()
48main()49#@help maxlen
deque(maxlen=N) automatically drops oldest items when full.
Reverse a list
Use deque to reverse element order.
from collections import deque
def main():
# Reverse a list using deque
numbers = [1, 2, 3, 4, 5]
print("=== Reversing a List ===")
print(f"Original: {numbers}")
# Method 1: Using deque as stack
stack = deque(numbers)
reversed_list = []
while stack:
reversed_list.append(stack.pop())
print(f"Reversed: {reversed_list}")
# Method 2: Using reverse() method
d = deque([1, 2, 3, 4, 5])
d.reverse() # In-place reverse
print(f"Using reverse(): {list(d)}")
# Method 3: Using reversed()
d2 = deque(reversed(deque([1, 2, 3, 4, 5])))
print(f"Using reversed(): {list(d2)}")
# Reverse a string
print("\n=== Reversing a String ===")
original = "Hello World"
stack = deque(original)
reversed_chars = []
while stack:
reversed_chars.append(stack.pop())
reversed_string = "".join(reversed_chars)
print(f'Original: "{original}"')
print(f'Reversed: "{reversed_string}"')
# Simpler Python way (for comparison)
print(f'Pythonic: "{original[::-1]}"')
# Practical: Check for balanced brackets
print("\n=== Balanced Brackets Check ===")
def is_balanced(s):
stack = deque()
pairs = {')': '(', ']': '[', '}': '{'}
for char in s:
if char in '([{':
stack.append(char)
elif char in ')]}':
if not stack or stack.pop() != pairs[char]:
return False
return len(stack) == 0
test_cases = ["()", "()[]{}", "(]", "([)]", "{[()]}", "((())"]
for test in test_cases:
result = "✓ Balanced" if is_balanced(test) else "✗ Not balanced"
print(f'"{test}" → {result}')
main()
main()
67main()68#@help reversenumbers ← [1, 2, 3, 4, 5], stack ← deque([1, 2, 3, 4, 5]), reversed_list ← []
3#@var=default,reverseString4def main():5 # Reverse a list using deque #?reverse6 numbers→ [1, 2, 3, 4, 5] = [1, 2, 3, 4, 5]7 8 print("=== Reversing a List ===")9 print(f"Original: {numbers[1, 2, 3, 4, 5]}")10 11 # Method 1: Using deque as stack12 stack→ deque([1, 2, 3, 4, 5]) = deque(numbers[1, 2, 3, 4, 5])13 reversed_list→ [] = []output=== Reversing a List === Original: [1, 2, 3, 4, 5]reversed_list ← [5], stack ← deque([1, 2, 3, 4])
pass 1 of 515while stackdeque([1, 2, 3, 4, 5]):16 reversed_list→ [5].append(stack→ deque([1, 2, 3, 4]).pop())All 5 passes — pass 1 is the card above pass reversed_liststack1 [] → [5] deque([1, 2, 3, 4, 5]) → deque([1, 2, 3, 4]) 2 [5] → [5, 4] deque([1, 2, 3, 4]) → deque([1, 2, 3]) 3 [5, 4] → [5, 4, 3] deque([1, 2, 3]) → deque([1, 2]) 4 [5, 4, 3] → [5, 4, 3, 2] deque([1, 2]) → deque([1]) 5 [5, 4, 3, 2] → [5, 4, 3, 2, 1] deque([1]) → deque([]) d ← deque([1, 2, 3, 4, 5]), d2 ← deque([5, 4, 3, 2, 1]), original ← Hello World
18print(f"Reversed: {reversed_list[5, 4, 3, 2, 1]}")1920# Method 2: Using reverse() method #?method21d→ deque([1, 2, 3, 4, 5]) = deque([1, 2, 3, 4, 5])22d→ deque([5, 4, 3, 2, 1]).reverse() # In-place reverse23print(f"Using reverse(): {list(ddeque([5, 4, 3, 2, 1]))}")2425# Method 3: Using reversed()26d2→ deque([5, 4, 3, 2, 1]) = deque(reversed(deque([1, 2, 3, 4, 5])))27print(f"Using reversed(): {list(d2deque([5, 4, 3, 2, 1]))}")2829# Reverse a string #?string #@var=!,_30print("\n=== Reversing a String ===")31original→ Hello World = "Hello World"3233stack→ deque(['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd']) = deque(originalHello World)34reversed_chars→ [] = []35while stack:outputReversed: [5, 4, 3, 2, 1] Using reverse(): [5, 4, 3, 2, 1] Using reversed(): [5, 4, 3, 2, 1] === Reversing a String ===reversed_chars ← ['d'], stack ← deque(['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l'])
pass 1 of 1134reversed_chars = []35while stackdeque(['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd']):36 reversed_chars→ ['d'].append(stack→ deque(['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l']).pop())All 11 passes — pass 1 is the card above pass reversed_charsstack1 [] → ['d'] deque(['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd']) → deque(['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l']) 2 ['d'] → ['d', 'l'] deque(['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l']) → deque(['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r']) 3 ['d', 'l'] → ['d', 'l', 'r'] deque(['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r']) → deque(['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o']) 4 ['d', 'l', 'r'] → ['d', 'l', 'r', 'o'] deque(['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o']) → deque(['H', 'e', 'l', 'l', 'o', ' ', 'W']) 5 ['d', 'l', 'r', 'o'] → ['d', 'l', 'r', 'o', 'W'] deque(['H', 'e', 'l', 'l', 'o', ' ', 'W']) → deque(['H', 'e', 'l', 'l', 'o', ' ']) 6 ['d', 'l', 'r', 'o', 'W'] → ['d', 'l', 'r', 'o', 'W', ' '] deque(['H', 'e', 'l', 'l', 'o', ' ']) → deque(['H', 'e', 'l', 'l', 'o']) 7 ['d', 'l', 'r', 'o', 'W', ' '] → ['d', 'l', 'r', 'o', 'W', ' ', 'o'] deque(['H', 'e', 'l', 'l', 'o']) → deque(['H', 'e', 'l', 'l']) 8 ['d', 'l', 'r', 'o', 'W', ' ', 'o'] → ['d', 'l', 'r', 'o', 'W', ' ', 'o', 'l'] deque(['H', 'e', 'l', 'l']) → deque(['H', 'e', 'l']) 9 ['d', 'l', 'r', 'o', 'W', ' ', 'o', 'l'] → ['d', 'l', 'r', 'o', 'W', ' ', 'o', 'l', 'l'] deque(['H', 'e', 'l']) → deque(['H', 'e']) 10 ['d', 'l', 'r', 'o', 'W', ' ', 'o', 'l', 'l'] → ['d', 'l', 'r', 'o', 'W', ' ', 'o', 'l', 'l', 'e'] deque(['H', 'e']) → deque(['H']) 11 ['d', 'l', 'r', 'o', 'W', ' ', 'o', 'l', 'l', 'e'] → ['d', 'l', 'r', 'o', 'W', ' ', 'o', 'l', 'l', 'e', 'H'] deque(['H']) → deque([]) reversed_string ← dlroW olleH, test_cases ← ['()', '()[]{}', '(]', '([)]', '{[()]}', '((())']
38reversed_string→ dlroW olleH = "".join(reversed_chars['d', 'l', 'r', 'o', 'W', ' ', 'o', 'l', 'l', 'e', 'H'])3940print(f'Original: "{originalHello World}"')41print(f'Reversed: "{reversed_stringdlroW olleH}"')4243# Simpler Python way (for comparison)44print(f'Pythonic: "{original[::-1]dlroW olleH}"')4546# Practical: Check for balanced brackets #?brackets47print("\n=== Balanced Brackets Check ===")4849def is_balanced(s):50 stack = deque()51 pairs = {')': '(', ']': '[', '}': '{'}52 53 for char in s:54 if char in '([{':55 stack.append(char)56 elif char in ')]}':57 if not stack or stack.pop() != pairs[char]:58 return False59 60 return len(stack) == 06162test_cases→ ['()', '()[]{}', '(]', '([)]', '{[()]}', '((())'] = ["()", "()[]{}", "(]", "([)]", "{[()]}", "((())"]63for test in test_cases:outputOriginal: "Hello World" Reversed: "dlroW olleH" Pythonic: "dlroW olleH" === Balanced Brackets Check ===for test in test_cases:
pass 1 of 662test_cases = ["()", "()[]{}", "(]", "([)]", "{[()]}", "((())"]63for test() in test_cases['()', '()[]{}', '(]', '([)]', '{[()]}', '((())']:64 result = "✓ Balanced" if is_balanced(test()) else "✗ Not balanced"65 print(f'"{test}" → {result}')All 6 passes — pass 1 is the card above pass teststackpairs[char]1 () — — 2 ()[]{} — — 3 (] deque([]) [ 4 ([)] deque(['(']) ( 5 {[()]} — — 6 ((()) — — stack ← deque([]), pairs ← {')': '(', ']': '[', '}': '{'}
pass 1 of 649def is_balanced(s()):50 stack→ deque([]) = deque()51 pairs→ {')': '(', ']': '[', '}': '{'} = {')': '(', ']': '[', '}': '{'}All 6 passes — pass 1 is the card above pass spairs[char]stackpairs1 () — deque([]) {')': '(', ']': '[', '}': '{'} 2 ()[]{} — deque([]) {')': '(', ']': '[', '}': '{'} 3 (] [ deque([]) {')': '(', ']': '[', '}': '{'} 4 ([)] ( deque([]) {')': '(', ']': '[', '}': '{'} 5 {[()]} — deque([]) {')': '(', ']': '[', '}': '{'} 6 ((()) — deque([]) {')': '(', ']': '[', '}': '{'} for char in s:
pass 1 of 2453for char( in s():54 if char in '([{':55 stack.append(char)24 passes — pass 1 is the card above pass charsstackpairs[char]1 ( () — — 2 ) () — — 3 ( ()[]{} — — 4 ) ()[]{} — — 5 [ ()[]{} — — 6 ] ()[]{} — — 7 { ()[]{} — — 8 } ()[]{} — — 9 ( (] — — ⋯ 13 more passes ⋯ 23 ) ((()) — — 24 ) ((()) — — stack ← deque(['('])
pass 1 of 1353for char in s:54 if char( in '([{':55 stack→ deque(['(']).append(char()56 elif char in ')]}':13 passes — pass 1 is the card above pass charpairs[char]stack1 ( — deque([]) → deque(['(']) 2 ( — deque([]) → deque(['(']) 3 [ — deque([]) → deque(['[']) 4 { — deque([]) → deque(['{']) 5 ( [ deque([]) → deque(['(']) 6 ( — deque([]) → deque(['(']) 7 [ ( deque(['(']) → deque(['(', '[']) 8 { — deque([]) → deque(['{']) 9 [ — deque(['{']) → deque(['{', '[']) ⋯ 2 more passes ⋯ 12 ( — deque(['(']) → deque(['(', '(']) 13 ( — deque(['(', '(']) → deque(['(', '(', '(']) elif char in ')]}':
pass 1 of 1155 stack.append(char)56elif char) in ')]}':57 if not stack or stack.pop() != pairs[char]:58 return FalseAll 11 passes — pass 1 is the card above pass charstackpairs[char]1 ) — — 2 ) — — 3 ] — — 4 } — — 5 ] deque([]) [ 6 ) deque(['(']) ( 7 ) — — 8 ] — — 9 } — — 10 ) — — 11 ) — — return len(stack) == 0
60return len(stackdeque([])) == 0result ← ✓ Balanced
63for test in test_cases:64 result→ ✓ Balanced = "✓ Balanced" if is_balanced(test()) else "✗ Not balanced"65 print(f'"{test()}" → {result✓ Balanced}')output"()" → ✓ Balancedreturn len(stack) == 0
60return len(stackdeque([])) == 0result ← ✓ Balanced
63for test in test_cases:64 result→ ✓ Balanced = "✓ Balanced" if is_balanced(test()[]{}) else "✗ Not balanced"65 print(f'"{test()[]{}}" → {result✓ Balanced}')output"()[]{}" → ✓ Balancedif not stack or stack.pop() != pairs[char]:
pass 1 of 256elif char in ')]}':57 if not stackdeque([]) or stack.pop() != pairs[char][:58 return Falseresult ← ✗ Not balanced
63for test in test_cases:64 result→ ✗ Not balanced = "✓ Balanced" if is_balanced(test(]) else "✗ Not balanced"65 print(f'"{test(]}" → {result✗ Not balanced}')output"(]" → ✗ Not balancedif not stack or stack.pop() != pairs[char]:
pass 2 of 256elif char in ')]}':57 if not stackdeque(['(']) or stack.pop() != pairs[char](:58 return Falseresult ← ✗ Not balanced
63for test in test_cases:64 result→ ✗ Not balanced = "✓ Balanced" if is_balanced(test([)]) else "✗ Not balanced"65 print(f'"{test([)]}" → {result✗ Not balanced}')output"([)]" → ✗ Not balancedreturn len(stack) == 0
60return len(stackdeque([])) == 0result ← ✓ Balanced
63for test in test_cases:64 result→ ✓ Balanced = "✓ Balanced" if is_balanced(test{[()]}) else "✗ Not balanced"65 print(f'"{test{[()]}}" → {result✓ Balanced}')output"{[()]}" → ✓ Balancedreturn len(stack) == 0
60return len(stackdeque(['('])) == 0result ← ✗ Not balanced
63for test in test_cases:64 result→ ✗ Not balanced = "✓ Balanced" if is_balanced(test((())) else "✗ Not balanced"65 print(f'"{test((())}" → {result✗ Not balanced}')output"((())" → ✗ Not balancedmain()
67main()68#@help reverse
Push all items to right, pop from left - they come out reversed.
Exercise: rotate.py
Explore deque.rotate() for circular shifts