6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

株式会社ディーバAdvent Calendar 2023

Day 16

【Python】非推奨になった関数やメソッドのリプレイス工程にとっても便利な`typing_extensions.deprecated`

Last updated at Posted at 2023-12-15

はじめに

ある関数やメソッドを非推奨にして今後リプレイスしていくということは開発時によくあることだと思います。

しかし、特徴的な使われ方や名前であるならまだしも、使われ方も名前も似ている関数やメソッドがそのようなリファクタリングの対象だと非常に視認性が悪く作業効率が低下しうっかりバグを埋め込んでしまうかもしれません。

# 下記のようなディレクトリ構成と仮定
# .
# ├── __init__.py
# ├── demo.py <- このファイル
# ├── lib_a.py
# └── lib_b.py

# demo.py
from . import lib_a, lib_b


def main():
    lib_a.foo()
    lib_b.foo()

if __name__ == "__main__":
    main()

このようなコードで「lib_a.fooは非推奨でリプレイスするけど、lib_b.fooはそうではないので気を付けて」と言われたら、かなり慎重な作業をしなければならず精神的に疲弊してしまうでしょう。

これを解決するのがPEP702で導入されPython3.13より標準ライブラリ入りする予定のtyping_extensions.deprecatedです。

ランタイムの動作について

typing_extensions.deprecatedはデコレータとして使われ、実行時に呼び出されると引数に渡した文字列のメッセージを持つDeprecationWaringを表示します。

# lib_a.py
from typing_extensions import deprecated


@deprecated("削除予定")
def foo():
	...
>>> python -m samples.demo
...\samples\demo.py:10: DeprecationWarning: 削除予定
  lib_a.foo()

これだけであればよくある実行時に非推奨であることを表示する仕組みです。
typing_extensions.deprecatedの真価は、VSCodeのPylanceのような、IDEと型チェッカーが組み合わさった開発環境で発揮されます。

IDE表示の変化について

VSCode・Pylanceによって、typing_extensions.deprecatedでデコレートされた関数には打ち消し線が引かれます
image.png
かつ、マウスオーバーするとツールチップには引数に取ったメッセージを表示してくれます
image.png

これは非常に視認性がよく、単体テストが網羅していない場合でも型チェッカーが静的解析で探してくれるため非常に便利です。

一部の呼び方だけ非推奨にする

デフォルト値付きの引数を持つ関数が引数名なしで呼び出されている場合、一見してパラメータの意味が分からないときがあります。

def main():
    lib_b.bar()  # 引数なしで呼び出せるのか。
    lib_b.bar(30)  # 30ってなに?
    lib_b.bar(timeout=20)  # やっと意味が分かった!

これの視認性をよくするために、今後のコードでは引数名を指定することを推奨したいです。
しかし、実装をdef lib_b.bar(*, timeout=60)としてしまうと引数なしで呼び出されている既存コードで実行時エラーとなってしまいます。
そんなとき、typing.overloadtyping_extensions.deprecatedを組み合わせると実行時エラーを起こすことなく同じ関数の特定の呼び出し方をしている部分のみ、打ち消し線をIDEで表示させることができます。

from typing_extensions import overload
from typing_extensions import deprecated


@overload
def bar(): ...
@overload
@deprecated("タイムアウトは名前付きで指定すること")
def bar(timeout, /): ...
@overload
def bar(*, timeout=...): ...

def bar(timeout=60):
    ...

image.png

この使用法の注意点としては、overloaddeprecatedでデコレートした呼び出し方で呼び出しても、実行時にDeprecationWarningは表示されないことです
関数の呼び出し方による警告を実行時にも表示するには、そのための分岐を別途実装に追加していく必要があります。

まとめ

VSCode・Pylancetyping_extensions.deprecatedの組み合わせは、非推奨となった関数やメソッドを視認性よく表示させる強力な機能です。
Python3.13以降は標準ライブラリ内部にwarnings.deprecatedとして追加されるので、特別な用意をすることなくリファクタリングの役に立つこの機能を使えるようになります。
これによって、実行時の動作への影響をなるべく抑えたリファクタリングがはかどっていくと考えています。

6
1
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
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?