Pythonの関数でのデフォルト引数の使い方と注意点

Modified: | Tags: Python

Pythonの関数定義でデフォルト引数を設定すると、関数呼び出し時に引数を省略した場合にデフォルト値が使用されるようになる。リストや辞書などの更新可能(ミュータブル)なオブジェクトをデフォルト値として指定する場合は要注意。

Pythonの関数についての基本的な説明は以下の記事を参照。

デフォルト引数の設定

関数定義で引数名=デフォルト値とすると、呼び出し時に該当の引数が省略されたときにデフォルト値が使われるようになる。

def func_default(arg1, arg2='default_x', arg3='default_y'):
    print(arg1)
    print(arg2)
    print(arg3)

func_default('a')
# a
# default_x
# default_y

func_default('a', 'b')
# a
# b
# default_y

func_default('a', arg3='c')
# a
# default_x
# c

デフォルト引数の位置の制約

関数定義時にデフォルト引数を通常の引数(デフォルト値を指定していない引数)の前に置くとエラー(SyntaxError)になる。

# def func_default_error(arg2='default_a', arg3='default_b', arg1):
#     print(arg1)
#     print(arg2)

# SyntaxError: parameter without a default follows parameter with a default

リストや辞書をデフォルト値とした場合の注意点

リストや辞書などの更新可能(ミュータブル)なオブジェクトをデフォルト値として指定した場合、そのオブジェクトは関数定義時に生成され、該当の引数を省略して関数を呼び出すと同じオブジェクトが使われる。

デフォルト引数値は関数定義が実行されるときに左から右へ評価されます。 これは、デフォルト引数の式は関数が定義されるときにただ一度だけ評価され、同じ "計算済みの" 値が呼び出しのたびに使用されることを意味します。
8. 複合文 (compound statement) - 関数定義 — Python 3.13.3 ドキュメント

このため、例えばリストや辞書をデフォルト引数としてそれに要素を追加するような関数を定義し、その引数を省略して複数回呼び出すと、同じオブジェクトに繰り返し要素が追加されてしまう。

リストの場合の例。

def func_default_list(l=[0, 1, 2], v=3):
    l.append(v)
    print(l)

func_default_list([0, 0, 0], 100)
# [0, 0, 0, 100]

func_default_list()
# [0, 1, 2, 3]

func_default_list()
# [0, 1, 2, 3, 3]

func_default_list()
# [0, 1, 2, 3, 3, 3]

辞書の場合の例。

def func_default_dict(d={'default': 0}, k='new', v=100):
    d[k] = v
    print(d)

func_default_dict()
# {'default': 0, 'new': 100}

func_default_dict(k='new2', v=200)
# {'default': 0, 'new': 100, 'new2': 200}

これを防ぐには、デフォルト引数をNoneに設定して引数が省略されたときに関数内で新しいオブジェクトを生成するようにすればよい。

関数定義時ではなく関数が呼び出されるタイミングで毎回新たなオブジェクトが生成される。

def func_default_list_none(l=None, v=3):
    if l is None:
        l = [0, 1, 2]
    l.append(v)
    print(l)

func_default_list_none()
# [0, 1, 2, 3]

func_default_list_none()
# [0, 1, 2, 3]

関連カテゴリー

関連記事