krahets/hello-algo · error · IndexError

両端キューが空です

Error message

両端キューが空です

What it means

This IndexError (Japanese: '両端キューが空です' = 'deque is empty') is raised by ArrayDeque.peek_first() (array_deque.py:76) when the deque holds no elements. peek_first reads _nums[_front], which is meaningless when _size == 0. ArrayDeque is a fixed-capacity circular-array deque. Note pop_first() calls peek_first() internally, so the same exception propagates through pop_first() too.

Source

Thrown at ja/codes/python/chapter_stack_and_queue/array_deque.py:76

    def pop_first(self) -> int:
        """キュー先頭からデキュー"""
        num = self.peek_first()
        # 先頭ポインタを 1 つ後ろへ進める
        self._front = self.index(self._front + 1)
        self._size -= 1
        return num

    def pop_last(self) -> int:
        """キュー末尾からデキュー"""
        num = self.peek_last()
        self._size -= 1
        return num

    def peek_first(self) -> int:
        """キュー先頭の要素にアクセス"""
        if self.is_empty():
            raise IndexError("両端キューが空です")
        return self._nums[self._front]

    def peek_last(self) -> int:
        """キュー末尾の要素にアクセス"""
        if self.is_empty():
            raise IndexError("両端キューが空です")
        # 末尾要素のインデックスを計算
        last = self.index(self._front + self._size - 1)
        return self._nums[last]

    def to_array(self) -> list[int]:
        """出力用の配列を返す"""
        # 有効長の範囲内のリスト要素のみを変換
        res = []
        for i in range(self._size):
            res.append(self._nums[self.index(self._front + i)])
        return res

View on GitHub (pinned to 69932aed18)

Solutions

  1. Check `if not dq.is_empty(): dq.peek_first()`.
  2. When draining, loop on `while not dq.is_empty():`.
  3. Be aware push_first/push_last silently no-op when full (they print, not raise) — verify size after pushes if you depend on the element being present.
  4. Pair every peek/pop with a size() or is_empty() guard in calling code.

Example fix

// before
first = dq.peek_first()  # IndexError on empty

// after
first = dq.peek_first() if not dq.is_empty() else None
Defensive patterns

Strategy: validation

Validate before calling

if not dq.is_empty():
    first = dq.peek_first()
# remember: push_first silently no-ops (prints) when full — verify size after push

Type guard

def deque_has_first(dq: ArrayDeque) -> bool:
    return not dq.is_empty()

Try / catch

try:
    first = dq.peek_first()
except IndexError:
    first = None

Prevention

When it happens

Trigger: Calling peek_first() on a freshly constructed ArrayDeque (size 0). Calling peek_first() / pop_first() after draining all elements. Note: the capacity-full case is handled differently here — push_first only prints a warning and returns, it does NOT raise, so 'empty' is the only IndexError from peek/pop.

Common situations: Peeking before any push. Draining with repeated pop_first() and then peeking. Assuming the deque is non-empty after a push that silently failed because capacity was full (push_first prints but does not raise on full).

Related errors


AI-assisted analysis of krahets/hello-algo@69932aed18 (2026-08-13). Data as JSON: /api/errors/e67077e7d50f0268. Report an issue: GitHub.