How to Get the First and Last Elements of a Deque in Python
A deque (double-ended queue) from Python's collections module is a versatile data structure that allows efficient insertion and removal from both ends. Accessing the first and last elements is a common operation when using deques as queues, stacks, or sliding windows. In this guide, we'll show you multiple methods to retrieve these elements and explain when to use each approach.
Quick Answer
from collections import deque
dq = deque([10, 20, 30, 40, 50])
first = dq[0] # First element
last = dq[-1] # Last element
print(f"First: {first}, Last: {last}")
Output:
First: 10, Last: 50
Method 1: Using Index Access [0] and [-1] (Recommended)
The simplest and most common way to access the first and last elements is using square bracket indexing. This reads the values without modifying the deque:
from collections import deque
dq = deque(['apple', 'banana', 'cherry', 'date', 'elderberry'])
print(f"Deque: {dq}")
print(f"First element: {dq[0]}")
print(f"Last element: {dq[-1]}")
print(f"Deque after: {dq}") # Unchanged
Output:
Deque: deque(['apple', 'banana', 'cherry', 'date', 'elderberry'])
First element: apple
Last element: elderberry
Deque after: deque(['apple', 'banana', 'cherry', 'date', 'elderberry'])
This is the preferred method when you simply want to peek at the first or last element without removing it. It's an O(1) operation, making it very efficient.
Accessing by index on an empty deque raises an IndexError:
from collections import deque
empty_dq = deque()
print(empty_dq[0]) # IndexError: deque index out of range
Always check if the deque is non-empty before accessing:
if dq:
print(dq[0])
else:
print("Deque is empty")
Method 2: Using popleft() and pop() (Removes Elements)
The popleft() method removes and returns the first element, while pop() removes and returns the last element:
from collections import deque
dq = deque([10, 20, 30, 40, 50])
print(f"Before: {dq}")
first = dq.popleft() # Removes and returns first element
last = dq.pop() # Removes and returns last element
print(f"First: {first}")
print(f"Last: {last}")
print(f"After: {dq}") # Elements are removed
Output:
Before: deque([10, 20, 30, 40, 50])
First: 10
Last: 50
After: deque([20, 30, 40])
popleft() and pop() remove the elements from the deque. Only use them when you intend to consume the data, such as when processing items from a queue.
Handling empty deques:
from collections import deque
dq = deque()
try:
first = dq.popleft()
except IndexError:
print("Cannot pop from an empty deque")
Method 3: Using Iteration (For Special Cases)
If you need both the first and last elements and want to handle edge cases gracefully, you can use unpacking:
from collections import deque
dq = deque([10, 20, 30, 40, 50])
# Unpack first and last (only works for 2+ elements)
first, *middle, last = dq
print(f"First: {first}, Last: {last}")
Output:
First: 10, Last: 50
This approach creates intermediate lists and only works when the deque has at least 2 elements. A single-element deque will raise a ValueError. Use indexing ([0] and [-1]) for the general case.
Comparison of Methods
| Method | Returns | Modifies Deque | Empty Deque | Time Complexity |
|---|---|---|---|---|
dq[0] / dq[-1] | Element value | ❌ No | Raises IndexError | O(1) |
dq.popleft() / dq.pop() | Element value | ✅ Yes (removes) | Raises IndexError | O(1) |
first, *_, last = dq | Both values | ❌ No | Raises ValueError | O(n) |
Practical Examples
Using a Deque as a Queue (FIFO)
from collections import deque
# Task queue
tasks = deque(['task_1', 'task_2', 'task_3', 'task_4'])
# Peek at the next task without removing it
print(f"Next task: {tasks[0]}")
# Process the next task (removes it)
current = tasks.popleft()
print(f"Processing: {current}")
print(f"Remaining: {tasks}")
Output:
Next task: task_1
Processing: task_1
Remaining: deque(['task_2', 'task_3', 'task_4'])
Using a Deque as a Sliding Window
from collections import deque
# Fixed-size sliding window of last 3 values
window = deque(maxlen=3)
for value in [10, 20, 30, 40, 50]:
window.append(value)
if len(window) == window.maxlen:
print(f"Window: {list(window)} | "
f"First: {window[0]}, Last: {window[-1]}")
Output:
Window: [10, 20, 30] | First: 10, Last: 30
Window: [20, 30, 40] | First: 20, Last: 40
Window: [30, 40, 50] | First: 30, Last: 50
Safe Access with a Helper Function
from collections import deque
def peek_first(dq, default=None):
"""Return the first element or a default if empty."""
return dq[0] if dq else default
def peek_last(dq, default=None):
"""Return the last element or a default if empty."""
return dq[-1] if dq else default
# Non-empty deque
dq = deque([10, 20, 30])
print(f"First: {peek_first(dq)}")
print(f"Last: {peek_last(dq)}")
# Empty deque
empty = deque()
print(f"First: {peek_first(empty, 'N/A')}")
print(f"Last: {peek_last(empty, 'N/A')}")
Output:
First: 10
Last: 30
First: N/A
Last: N/A
Conclusion
- To get the first and last elements of a deque in Python, use index access with
dq[0]anddq[-1]. This is the simplest, fastest (O(1)), and safest approach because it does not modify the deque. - Use
popleft()andpop()only when you want to remove the elements while retrieving them (for example, when processing a queue). - Always check that the deque is non-empty before accessing elements to avoid
IndexError.