関数引数と辞書

関数引数にも辞書は大活躍!

tags:python, tips, experiment, def, dict
created:2007-02-05T20:24:24

関数引数にも辞書は大活躍! Pythonでは関数引数にも辞書(dictオブジェクト)が活躍しています。

基本

関数引数の表示

>>> def hoge(**keys):
...   print keys
...
>>> hoge(i=1, j=2)
{'i': 1, 'j': 2}

このように、名前つき引数はダブルアスタリスクをつけたプレースホルダに辞書として格納されます。

そして、dictオブジェクトコンストラクタもこの名前つき引数から辞書の作成が出来るようになっています。

>>> dict(a=1,b=2)
{'a': 1, 'b': 2}

この方法で辞書定義を少し楽に出来ますね。 (通常ならキーの名前をいちいち文字列としてクオーテーションで囲まなくてはなりません)

また、辞書オブジェクトを名前つき引数に展開して渡すには呼び出し時にダブルアスタリスクをつけます。

>>> hoge(**dict(a=1,b=2))
{'a': 1, 'b': 2}

引数省略時の値との併用

>>> def hoge(id=-1, **keys):
...   print id, keys
...
>>> hoge()
-1, {}
>>> hoge(id=1)
1, {}
>>> hoge(2)
2, {}
>>> hoge(a=1, b=2)
-1, {'a': 1, 'b': 2}
>>>

ダブルアスタリスクのプレースホルダには明示していないものの 残り が格納されます。

つまり、明示しているものは keys に格納されません。

>>> def hoge(id=-1, **keys):
...   print locals()
...
>>> hoge(1, b=2, c=3)
{'keys': {'c': 3, 'b': 2}, 'id': 1}

このように、明示した引数と明示していない引数すべてを参照するにはlocals()をつかって参照する事は出来ます。(ただしフラットではないですが)

シングルアスタリスクのプレースホルダも

シングルアスタリスクのプレースホルダを記述することも出来ます。

この場合、辞書としてではなく、タプルとして扱います。

>>> def hoge(*args):
...  print type(args),args
...
>>> hoge(1,2,3)
<type 'tuple'> (1, 2, 3)

このプレースホルダでは、名前なしの引数のうち、明示していない 残り を列挙します。

混在させる時の留意点

>>> def hoge(*args, **keys):
...   print args, keys
...

このように記述するとすべての引数にアクセスでき、 どんな引数群を渡してもエラーになりません。

しかし、これらのプレースホルダは記述順が決められています。

>>> def hoge(**keys, *args):
  File "<stdin>", line 1
    def hoge(**keys, *args):
                   ^
SyntaxError: invalid syntax

このようにシンタックスエラーになってしまいます。

順番は、

  1. 省略時値指定なし引数群
  2. 省略時値指定あり引数群
  3. シングルアスタリスクプレースホルダ
  4. ダブルアスタリスクプレースホルダ

の順番でなくてはなりません。

>>> def hoge(a, b, c=5, *args, **keys):
...   print a,b,c, args, keys
...
>>> hoge(1,2)
1 2 5 () {}
>>> hoge(0,1,moge='hello!')
0 1 5 () {'moge': 'hello!'}
>>> hoge(0,1,2,3,4,moge='hello!')
0 1 2 (3, 4) {'moge': 'hello!'}

つまり、この関数宣言では 必須 の引数を2つとし、 オプションで

  • 「c」(省略時は5になる)
  • その他の名前なし引数群
  • その他の名前つき引数群

を渡せる関数宣言ということになります。

結論

柔軟な関数宣言が出来るおかげで、ひとつの関数の役割を拡大することが出来ますね。

C++でいうところのオーバーロードが出来ない仕様になっていますが、今回の定義方法を使って 引数型判定を自前で実装することで、引数に応じた処理実装を作ることが出来ます。

また、Python2.4では マルチメソッドデコレータ という手法が考案されています。 (by Guido van Rossum)

Pythonでは、いろんなところでこの辞書オブジェクトが活躍しています。 ぜひ今回紹介した基本を知っておいてからいろんなPythonソースコードを読んでみてください!