続・関数の引数

【 目次 】

関数の引数について、述べ足りなかった事があったので。

引数について

いまさらながら、プログラミングにおける関数の引数仮引数実引数とは

  • 引数 - Wikipedia

    外部から値を渡される特別な変数として指定されるのが仮引数。関数(等)を呼出す式において、仮引数に対応する式(あるいはその値)が実引数である。実行時には、実引数の値を仮引数が受け取る。

キーワード引数キーワード無しの引数のバリエーション

キーワード引数についてのまとめ」でキーワード引数にも使い方がいろいろあると述べた。

キーワード引数キーワード無しの引数の指定の仕方の組み合わせで、関数呼び出し時に指定した引数(実引数)が関数のどの引数(仮引数)に渡されるかに、いろいろなパターンがあって思わぬ結果になるので注意!

しつこいようだが、あらためてまとめてみた。
「そんな事、わかっているよ」と言われそうだが。

以下のような関数funcが定義されているとすると

def func(arg1, arg2, *args, **kwargs):
    print "arg1=", arg1
    print "arg2=", arg2
    print "args=", args
    print "kwargs=", kwargs

キーワード無しの引数を指定

以下のように引数をすべてキーワード無しの引数で指定すると

func("arg1", "arg2", "arg3", "arg4")

実行結果

arg1= arg1
arg2= arg2
args= ('arg3', 'arg4', 'arg5')
kwargs= {}

必須の引数以外の残りの引数はすべてargsに格納される。
キーワード無しなのでkwargsには何も渡されない。

キーワード付き引数を指定

全ての引数をキーワード付き引数で指定すると

func(arg5="arg5", arg4="arg4", arg3="arg3", arg2="arg2", arg1="arg1")

実行結果

arg1= arg1
arg2= arg2
args= ()
kwargs= {'arg3': 'arg3', 'arg4': 'arg4', 'arg5': 'arg5'}

名前付きなので引数の順番は関係ない。
今度はargsには何も渡されない。
必須の引数以外の残りの引数はすべてkwargsに格納される。

キーワード付き引数の後ろにキーワード無しの引数は指定できない。

キーワード付き引数の後ろにキーワード無しの引数を指定すると

func(arg1="arg1", "arg2", arg3="arg3", "arg4", arg5="arg5")

実行結果

SyntaxError: non-keyword arg after keyword arg

キーワード無しの引数をキーワード付き引数の後に指定したとpythonに怒られた。

キーワード無しの引数とキーワード付き引数の混在指定

キーワード無しの引数とキーワード付き引数の混在指定すると

func("arg1", "arg2", "arg3", arg4="arg4", arg5="arg5")

実行結果

arg1= arg1
arg2= arg2
args= ('arg3',)
kwargs= {'arg4': 'arg4', 'arg5': 'arg5'}

必須の引数以外のキーワード無しの引数arg3はargsに、キーワード付きのarg4,arg5はkwargsに格納される。
しかし、次の場合には、

func("arg1", "arg2", arg3="arg3", arg4="arg4", arg5="arg5")

実行結果

arg1= arg1
arg2= arg2
args= ()
kwargs= {'arg3': 'arg3', 'arg4': 'arg4', 'arg5': 'arg5'}

arg3をキーワード付きに変更すると、当然の事ではあるがarg3もkwargsに格納される事になる。

*引数や**引数の引数名をキーワード付き引数として指定する事はできない

*引数や**引数の引数名argsやkwargsをキーワード付き引数として指定して

func("arg1", "arg2", args=("arg3", "args4"), kwargs={"arg5_key": "arg5_value"})

以下のような結果を期待しても、
ダメヨ、ダメダメ。

このような結果にはならない

args= ("arg3", "args4")
kwargs= {'arg5_key': 'arg5_value'}}

kwargs引数の辞書要素として、args要素とkwargs要素に格納されてしまう事になる。

実行結果

arg1= arg1
arg2= arg2
args= ()
kwargs= {'args': ('arg3', 'args4'), 'kwargs': {'arg5_key': 'arg5_value'}}

「引数リストのアンパック」と「キーワード付き引数」

引数リストのアンパックで述べたように*引数や**引数をまとめて渡す事ができる。

*引数にタプル値を渡すと

func("arg1", "arg2", *("arg3", "arg4"), arg5="arg5")

実行結果

arg1= arg1
arg2= arg2
args= ('arg3', 'arg4')
kwargs= {'arg5': 'arg5'}

更に、**引数に対しても辞書を渡してやると

func("arg1", "arg2", *("arg3", "arg4"), **{"arg5_key":"arg5_value", "arg6_key":"arg6_value"})

実行結果

arg1= arg1
arg2= arg2
args= ('arg3', 'arg4')
kwargs= {'arg5_key': 'arg5_value', 'arg6_key': 'arg6_value'}

しかし、キーワード引数に対してはこのような事(引数リストのアンパック)はできないようだ。
以下のコードはエラーになる。

func("arg1", "arg2", args=*("arg3", "arg4"), kwargs=**{"arg5_key":"arg5_value", "arg6_key":"arg6_value"})
ページのトップへ戻る