音楽ストリーミングサービスを提供する会社で働いています。
音楽プレイヤーアプリにプレイリスト機能を作る仕事を任されました。
音楽プレイヤーアプリケーションのプロトタイプを書いてみましょう。
プロトタイプでは、それぞれの曲を単純に数値で表します。数値の範囲(曲のID)が与えられたら、単方向連結リストを作成しましょう。
単方向連結リストが与えられたら、そのリストを逆順にして、曲を反対の順番で再生できるようにしましょう。
連結リストはコンピューターサイエンスにおける基本的なデータ構造で、ほかのデータ構造を実装するときによく使われます。
もっとも単純な連結リストは、単方向連結リストです。つまり、各要素(「ノード」)はデータを持ち、さらにリスト内の次のノードを指すものを持ちます。
連結リストについてもっと深く知りたい場合は、こちらの記事で、わかりやすい図を使って説明されています。
stacksやqueuesはlists、collections.deque、queue.LifoQueue、multiprocessing.Queueを使って実装できますが、この演習では、自作の単方向連結リストを使った「後入れ先出し」(LIFO)スタックを想定しています。
これは、内部でlistやqueue、arrayを使うかもしれない動的配列やリストを使ったLIFOスタックと混同しないでください。動的配列ベースのstacksは、headの位置が異なり、時間計算量(Big-O)やメモリ使用量も異なります。
これらの考慮点については、Stack Overflowの次の2つの質問を参照してください:配列ベースとリストベースのスタックとキューと、配列スタック、連結スタック、スタックの違い。
Pythonにおける連結リスト、LIFOスタック、その他の抽象データ型(ADT)の詳細については、次の資料をご覧ください:
ADTを扱っています)Pythonで連結リストを「標準的」に実装するには、通常1つ以上のclassesが必要です。
classesのよい入門としては、classesとその関連演習であるellens-alien-game、あるいはPython公式チュートリアルのクラスの節をご覧ください。
この演習のテストでは、LinkedListに対してlen()を呼び出します。
len()を機能させるには、__len__という特殊メソッドを作成する必要があります。
Pythonで特殊メソッドや"dunder"メソッドを実装する方法の詳細については、Pythonドキュメント: 基本的なオブジェクトのカスタマイズとPythonドキュメント: object.len(self)をご覧ください。
LinkedListをループでたどったり逆順にしたりできるようにするには、__iter__特殊メソッドを実装する必要があります。
実装の詳細については、クラスにイテレーターを実装する方法をご覧ください。
コードの中で例外をカスタマイズしたりraiseしたりする必要がある場合があります。
その際は、エラーの原因を示す意味のあるエラーメッセージを必ず含めてください。
そうするとコードが読みやすくなり、デバッグにも大いに役立ちます。
カスタム例外は、新しい例外クラスを作ることで作成できます(詳しくはclassesをご覧ください)。こうしたクラスは通常、Exceptionのサブクラスです。
エラーの原因が特定の例外_型_から派生したものであるとわかっている場合は、_Exception_クラスの下にあるbuilt in error typesのいずれかを継承するという選択肢があります。
エラーを送出するときも、意味のあるメッセージを含めるようにしてください。
この演習では、連結リストが空のときに送出される("thrown")_カスタム例外_を作成する必要があります。
テストに合格するには、適切な例外をカスタマイズし、その例外をraiseし、適切なエラーメッセージを含める必要があります。
汎用的な_例外_をカスタマイズするには、Exceptionを継承したclassを作成します。
メッセージ付きでカスタム例外を送出するときは、メッセージをexception型の引数として書きます:
# subclassing Exception to create EmptyListException
class EmptyListException(Exception):
"""Exception raised when the linked list is empty.
message: explanation of the error.
"""
def __init__(self, message):
self.message = message
# raising an EmptyListException
raise EmptyListException("The list is empty.")