カンテラの光の下で

dNaga392's memorandom

Pythonのデフォルト引数で注意すること

概要

  • 引数のデフォルト値は 1 度だけしか評価されない
  • つまり、デフォルト引数で指定した値は、関数実行ごとには初期化されない
  • (list や dict のような)変更可能なオブジェクトを指定したい場合は、代わりに None を指定するとよい

現象

関数のデフォルト引数値に、list や dict のように、変更可能(ミュータブル)なオブジェクトを指定したとき、 これは1度しか評価されず、2回目以降はそれを繰り返し使用する。

def f(a, L=[]):
    L.append(a)
    return L

print(f(1))  # => [1]
print(f(2))  # => [1, 2]
print(f(3))  # => [1, 2, 3]

この現象は、 Python ドキュメントに 重要な警告 として記載されている。

これは奇妙な現象にも思えるが、オブジェクトに対して変数を割り当てるという Python の視点から解釈すれば納得することもできるだろう (とはいえ、期待する動作ではないのだが。。。)。

対策

一般的に、このような場合は変更可能(ミュータブル)なオブジェクトの代わりに None を使用する。

def f(a, L=None):
    if L is None:
        L = []
    L.append(a)
    return L

print(f(1))  # => [1]
print(f(2))  # => [2]
print(f(3))  # => [3]

参考資料