たれぱんのびぼーろく

わたしの備忘録、生物学とプログラミングが多いかも

OmegaConf の入れ子構造化コンフィグ

OmegaConf は構造化コンフィグの入れ子(Nesting structured configs)をサポートしている(docs - Nesting structured configs)。
その際、default_factory の利用が推奨されている。

@dataclass
class Group:
    name:    str  = MISSING
    admin:   User = field(default_factory=User)
    manager: User = field(default_factory=lambda: User(name="manager", height=Height.TALL))

# modified from: https://omegaconf.readthedocs.io/en/latest/structured_config.html#nesting-structured-configs

上記の例で default_factory を使用しない場合、Group を2つ以上インスタンス化した場合に .admin.manager が意図せず共有オブジェクトになる。
上位 nested structured config で group1=Group, group2=Group のように書くとgroup1の変更がgroup2に意図せず伝播してしまう。

これはPythonの言語仕様による。
Pythonは言語仕様として「デフォルト引数の使い回し」をする。
デフォルト引数に mutable なオブジェクト(例: クラスインスタンス)を設定すると、関数定義時にインスタンス化してそれを各呼出しで使いまわす。
ゆえに意図しないオブジェクト共有が発生してバグの温床になる。
tarepan.hatenablog.com

これは言語仕様によるものなので default_factory の使用がほぼ必須。