12
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Python 3.10 以降では Optional や Union をわざわざインポートする必要が無くなって便利

Last updated at Posted at 2022-04-01

Noneを返す場合のある関数の型ヒントを書く場合、以前は以下のように書いていた

old.py
from pathlib import Path
from typing import Optional


def get_latest_log_path(search_dir: Path) -> Optional[Path]:
    """最新のログファイルのパスを取得する

    Returns:
        Optional[Path]: ログファイルが存在する場合、最新のログファイルのパス。存在しない場合は None
    """
    return max(
        search_dir.glob("**/*.log"),
        key=lambda path: path.stat().st_mtime,
        default=None,
    )


if __name__ == "__main__":
    print(get_latest_log_path(Path("log")))

Python 3.10 以降では以下のように書けるようになった

new.py
from pathlib import Path


def get_latest_log_path(search_dir: Path) -> Path | None:
    """最新のログファイルのパスを取得する

    Returns:
        Path | None: ログファイルが存在する場合、最新のログファイルのパス。存在しない場合は None
    """
    return max(
        search_dir.glob("**/*.log"),
        key=lambda path: path.stat().st_mtime,
        default=None,
    )


if __name__ == "__main__":
    print(get_latest_log_path(Path("log")))

差分

 from pathlib import Path
-from typing import Optional

-def get_latest_log_path(search_dir: Path) -> Optional[Path]:
+def get_latest_log_path(search_dir: Path) -> Path | None:
     """最新のログファイルのパスを取得する

Optional と Union について

https://docs.python.org/ja/3/library/typing.html#typing.Union

Optional[X] を Union[X, None] の略記として利用することが出来ます
バージョン 3.10 で変更: Unions can now be written as X | Y
str | None == typing.Optional[str]

つまり、Optional[Path]Path | None は同じということ
それなら後者の方が簡潔で良いと思った

追記

記事を作成後に @ye_lp さんが「もっと良い書き方があるよ」
と Twitter にて教えてくださって、上記のコードになりました
元のコードは↓でした

old.py
import os
from pathlib import Path


def main():
    print(get_latest_log_path())


def get_latest_log_path() -> Path | None:
    """最新のログファイルのパスを取得する"""
    logs: list[os.DirEntry] = []
    with os.scandir(Path("log")) as it:
        for entry in it:
            if entry.name.endswith(".log"):
                logs.append(entry)
    if len(logs) == 0:
        return None
    latest = logs[0]
    for log in logs:
        if log.stat().st_mtime > latest.stat().st_mtime:
            latest = log
    return Path(latest.path)


if __name__ == "__main__":
    main()

こうして見ると元々のコードは微妙な書き方をしていたなと思います。
Pythonic なコードを教えて頂き感謝です!

12
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?