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 なコードを教えて頂き感謝です!