メソッド呼び出し元で引数が指定されていない場合は、デフォルト値を与えられます。キーワード引数を使用すると、任意のパラメータに値を与えられます。
ただし、意図的にメソッド呼び出し元でNone
を渡してしまった場合、デフォルト値を使用できません。
今回の記事では、パラメータの値がNoneの場合はメソッドに渡さず、値が含まれている場合はメソッドに渡します。
前提
- Python
- 3.11
対応
辞書型をパラメータに使用します。辞書型で**
を使用するとキーワード引数に展開されて使用できます。
class DictDomain: @staticmethod def action(a: str = "1", b: str = "2", c: str = "3"): print(a, b, c) def test_param_method(): dict = {"a": "a", "b": "b", "c": None} DictDomain.action(**dict) # print文の結果 # a b None
辞書型で値がNoneの時にキーを削除する処理をします。
def test_param_method(): dict = {"a": "a", "b": "b", "c": None} all_key_has_value = {k: v for k, v in dict.items() if v is not None} DictDomain.action(**all_key_has_value) # print文の結果 # キーワードに渡されていないので、デフォルトの3が出力される # a b 3
ただ私が慣れていないこともあり、非常に読みづらいので必要な項目だけ辞書型に絞ったほうが分かりやすいと思います。
def test_param_method(): dict = {"c": None} all_key_has_value = {k: v for k, v in dict.items() if v is not None} DictDomain.action("a"="a", "b"="b", **all_key_has_value)
注意点
辞書型を動的に加工するので静的解析が効きません。具体的には定義していないキーワードを指定していても、静的解析が効かなくなるのでTypoをした場合に気付くタイミングが遅れてしまいます。画像はVSCodeの警告の有無を表現しています。
import pytest def test_undifined_parameter(): with pytest.raises(TypeError): param = {"d": 1} DictDomain.action(**param) param2 = {k: v for k, v in param.items() if v is not None} DictDomain.action(**param2)
ソースコード
終わりに
Factory_boy
を使用してデータのセットアップをしていましたが、NotNull
で定義している項目に対してNone
を設定するとValidationError
が発生します。このエラーを回避しようとしましたがFactory_boy
側で回避する方法が見つからなかったため、呼び出し側で対処するようにしました。
テストコードなので次のコードのように単純化しようとしましたが、項目が多かったのと共通化したかったので、今回の方式を取ろうとしています。
if c: DictDomain.action("a"="a", "b"="b", "c"=c) else: DictDomain.action("a"="a", "b"="b")
非常に使い道のうすい使い方だと思っていますが、ぜひ使ってみてください。