可変長引数
可変長引数は、その名の通り引数の長さを自由に変えられる引数。
なので、どんな数の引数を渡しても対応できる関数となるわけです。
関数の引数に*または**をつけると定義できます。
可変長引数は各々ひとつづつしか定義できません。
※ややこしかったので、うまくまとまってないかもしれないです。
まず、簡単なサンプルから
$ python3
Python 3.5.0 ()
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def print_parameters(*arguments, **keyword_arguments):
... print('args =', arguments)
... print('kwargs =', keyword_arguments)
...
>>> print_parameters(1,2,3,4, a=4, b=3, c='hoge')
args = (1, 2, 3, 4)
kwargs = {'c': 'hoge', 'b': 3, 'a': 4}
簡単な使い方としてはこんな感じです。
(*argsはarguments, kwargsはkeyword argumentsのことです)
*argumentsのように*を付けると普通の引数をtupleにしてまとめてくれます。
**keyword_argumentsのように**をつけるとkeyword引数をdictにまとめてくれます。当然ながら、=の左側には半角数字で始まるものは書けません。
普通の引数を混ぜる
絶対に引数として受け取るものがある場合。
*がついてる引数の前後に置くことができます。
keyword引数は引数の最後に書く決まりがあるので、**の後ろには何も引数を書くことができません。
この際の注意点としては、*がついてる引数の前に置いた引数をkeyword引数として書けない。
*の後ろに置いた引数はkeyword引数として書かなければいけないことです。
>>> def print_parameters(flag, *arguments, length, **keyword_arguments):
... print(flag, length)
... print('args =', arguments)
... print('kwargs ='keyword_arguments)
>>> print_parameters(True,1,2,3,4,length=4, args=4, a=3, c='hoge')
True 4
(1, 2, 3, 4)
{'args': 4, 'c': 'hoge', 'a': 3}
>>> print_parameters(True, length=0)
True 0
args = ()
kwargs - {}
エラー例:flagをkeyword引数とした場合
>>> print_parameters(1, 2, 3, 4,flag=False, length=4, args=4, a=3, c='hoge')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: print_parameters() got multiple values for argument 'flag'
エラー例:lengthをkeyword引数で書かなかった場合
>>> print_parameters(True,1,2,3,4,4, args=4, a=3, c='hoge')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: print_parameters() missing 1 required keyword-only argument: 'length'
このように、エラーを吐き出してきます。
おそらく、引数は手前から処理するので、flagの場合は先に1が代入されているのにkeyword引数でflag=Falseとまたflagをいじろうとしたのでエラーが出た。
lengthの場合*argumentsが1,2,3,4,4をすべて受け取ってしまうためlengthに入るものがなくなってしまったという感じだと思います。
この際、lengthに関数を定義する際にデフォルト値を設定すればエラーは起こりません。
list(tuple)やdictの中身を引数として渡すには
ここからは、可変長引数を使っていますが、あまり可変長引数とは関係なく、基礎の話です。
普通に渡すと、
>>> def print_parameters(flag, *arguments, length, **keyword_arguments):
... print(flag, length)
... print('args =', arguments)
... print('kwargs =`, keyword_arguments)
>>> print_parameters(True, [1,2,3,4,5], {'a':5, 'b':2} , length=2)
True 2
args = ([1, 2, 3, 4, 5], {'b': 2, 'a': 5})
kwargs = {}
list, dictそれぞれ一つの変数として*argumentに入ります。
list(tuple)を各要素を引数として渡したい場合は
>>> print_parameters(*[True, 1,2,3,4,5], 6, length=6)
True 6
args = (1, 2, 3, 4, 5, 6)
kwargs = {}
このように、*をlistの前につけることでひとつひとつ渡すことができます。
次に、dictをkeyword引数として渡したい場合は
>>> print_parameters(**{'flag':True, 'length':5, 'a':0, 'b':1}, c=1, d=3)
True 5
args = ()
kwargs = {'c': 1, 'd': 3, 'b': 1, 'a': 0}
dictの場合は**をつけることでkeyword引数に混ぜることができます。
もともと関数で定義されているkeyword(flagとlength)はそっちにに代入され、それ以外はkeyword_argumentsに入ります。
dictは*をひとつだけつけた場合には、keyをすべて渡してくれます。
>>> dic = {'flag':True, 'length':0, 'a':1, 'b':2}
>>> print_parameters(True, *dic, length=4)
True 4
args = ('flag', 'b', 'a', 'length')
kwargs = {}
こんな感じになります。
まとめ
今回、可変長引数について書きました。
**はkeyword引数をdictにまとめてくれる。(定義されているkeyword引数は別)
*は引数をtupleにまとめてくれる。
keyword引数は一番右にまとめて書く。
可変長引数、keyword可変長引数はひとつの関数に各々ひとつしか書けない。