【python3】オプショナル引数のundefinedを見分けたい

 pythonで、optional引数を受け取ったとき、それがNoneなのか、undefinedなのかを見分けたい場合があります。

例えば、データベースのレコード更新処理で、明示的にNoneが入っていればnullで当該列を更新したいが、何も指定されていない場合は更新したくない、などの処理が考えられます。

kwargsに当該キーが存在するかを調べる

 通常であれば、kwargsに当該キーがあるかどうかを調べるのですが、これだとコード補完が効きませんし、インターフェースから引数の情報を読み取ることができませんから、実装を見に行くことになります。そうなるとスムーズなコードリーディングを妨げてしまいます。

def hoge(a, b, *, **kwargs):
  if "c" not in kwargs:
    print("c is undefined!!")

ユニークな初期値を渡す

 そこで、_UNDEFINEDという、引数として渡されることのないobjectを初期値として渡し、これが設定されているかを確認することによって、明示的に値が設定されているかどうかを知ることができます。

_UNDEFINED = object()
def hoge(a, b, *, c=_UNDEFINED):
  if c is _UNDEFINED:
    print("c is undefined!!")

 もちろん、呼び出し側で _UNDEFINED をインポートし、無理やり渡すことで関数を騙すことはできますが、そういったハックはレビューでrejectされることでしょう。

まとめ

 こういったテクニックを使うことは稀ですが、覚えておくと応用出来る日が来るかもしれません。