Search on the blog

2017年5月23日火曜日

Pythonのデフォルト値の罠

 Pythonのデフォルト値ではまったところがあったのでメモ。以下のプログラムを例に考える。
def add_key_value_to_dict(k, v, d={}):
  d[k] = v;
  return d

if __name__ == "__main__":
  x = add_key_value_to_dict("aa", "bb", {"xx": "yy"})
  print (x)

  y = add_key_value_to_dict("hoge", "fuga")
  print (y)
  
  z = add_key_value_to_dict("foo", "bar")
  print (z)
これを実行すると以下のような結果が出力される。
{'aa': 'bb', 'xx': 'yy'}
{'hoge': 'fuga'}
{'hoge': 'fuga', 'foo': 'bar'}

1行目と2行目の結果は予想どおりだが、3行目の結果はPythonに詳しくない人には意外かもしれない。

実はPythonのデフォルト値はdefステートメントが実行されるときだけ評価される。つまりデフォルト値がmutableな値の場合、関数内で実行した変更は副作用をもたらすことになる。上の例では、dict型の引数dのデフォルトは最初は{}だが、そのあとyを計算するときに{'hoge': 'fuga'}に更新され、さらにzの計算時に{'hoge': 'fuga', 'foo': 'bar'}に更新される。

デフォルト値にmutableな値を指定すると予想しない挙動になることがあるため、以下のようにimmutableな値を使用するとよい。

def add_key_value_to_dict(k, v, d=None):
  if d is None:
    d = {}
  d[k] = v;
  return d

if __name__ == "__main__":
  x = add_key_value_to_dict("aa", "bb", {"xx": "yy"})
  print (x)

  y = add_key_value_to_dict("hoge", "fuga")
  print (y)
  
  z = add_key_value_to_dict("foo", "bar")
  print (z)

上のコードの実行結果は以下のとおり。
{'aa': 'bb', 'xx': 'yy'}
{'hoge': 'fuga'}
{'foo': 'bar'}

0 件のコメント:

コメントを投稿