PythonでJavaのOptionalクラスを実装する
Pythonで型ヒントが使えるようになってから、mypyなどの型の静的解析の活用もあいまってPythonでプロダクションレベルの開発がしやすくなった。 ただ、JavaのOptionalクラスのような、Noneの扱う便利クラス/メソッドは言語レベルでは提供されていないため、自前かライブラリを利用する必要がある。
型ヒントを活用して、JavaのOptionalクラスの一部の機能を実現するOptionクラスを実装した。Optionalは型ヒントですでに使用されているため、クラス名はOptionとした。
from typing import Callable, Generic, Optional, TypeVar T = TypeVar("T") U = TypeVar("U") """JavaのOptionalクラスを実現するクラス """ class Option(Generic[T]): """コンストラクタ JavaのOptionalクラスが持つof、ofNullableメソッドの機能をコンストラクタで担う。 Javaのofメソッドに相当する、None非許容のコンストラクタは作らない。 :param value: 値 :return: インスタンス """ def __init__(self, value: Optional[T]): self.__value = value """値を返すメソッド。JavaのOptionalクラスと異なり、値がNoneでも例外は投げない。 :return: 値 """ def get(self) -> Optional[T]: return self.__value """値が存在する場合はTrue、そうでない場合はFalseを返す。 :return: 値が存在する場合はTrue、そうでない場合はFalse """ def is_present(self) -> bool: return self.__value is not None """値が存在する場合は値を返し、そうでない場合はotherを返す。 :param other: Noneの場合に返す値 :return: Optionの値かother """ def or_else(self, other: T) -> T: return self.__value or other """マッピング関数をその値に適用した結果をOptionで返す。valueがNoneの場合は空のOptionを返す。 :param mapper: マッピング関数 :return: マッピング関数を適用した結果 """ def map(self, mapper: Callable[[T], U]) -> "Option[U]": if self.__value is None: return Option(None) return Option(mapper(self.__value)) """値が存在し、その値が与えられた述語に一致する場合は、値を記述するOptionを返し、それ以外の場合は空のOptionを返す。 :param predicate: フィルター関数 :return: フィルターを適用した結果 """ def filter(self, predicate: Callable[[T], bool]) -> "Option[T]": if self.__value is None: return Option(None) return self if predicate(self.__value) else Option(None)