関数定義で引数のデフォルト値を設定できる
def foo(bar=[]):
bar.append('baz')
return bar
foo()
を実行すると、['baz']
というリストが返ってくる
>>> foo()
['baz']
さて同じコードをもう一度実行するとどうなるだろうか?
>>> foo()
['baz', 'baz']
結果が変わってしまっている。何故このようなことになるかというと、Pythonでは関数のデフォルト値は最初の一回しか評価されないためだ。そして、Pythonのリストは変更可能なオブジェクト(mutable)であり、append()
はリストに対し破壊的に引数を追加するため、2回目の実行で予期しない結果が返ってきてしまうことになる。
この問題をクリアするにはimmutableなオブジェクトをデフォルトにすればいい。今回のfoo
関数の場合だと
def foo(bar=None):
if bar is None:
bar = []
bar.append('baz')
return bar
のようにする。この関数は何度引数なしで呼び出しても、Noneはimmutableなので毎回同じ結果を返す。
>>> foo()
['baz']
>>> foo()
['baz']
Pythonではstrはimmutableなので文字列をデフォルト値として用いるのは特に問題ない。