Edited at

可変長引数

More than 3 years have passed since last update.


可変長引数

可変長引数は、その名の通り引数の長さを自由に変えられる引数。

なので、どんな数の引数を渡しても対応できる関数となるわけです。

関数の引数に*または**をつけると定義できます。

可変長引数は各々ひとつづつしか定義できません。

※ややこしかったので、うまくまとまってないかもしれないです。

まず、簡単なサンプルから


easy_sample.

$ 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引数として書かなければいけないことです。


sample.

>>> 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の場合*arguments1,2,3,4,4をすべて受け取ってしまうためlengthに入るものがなくなってしまったという感じだと思います。

この際、lengthに関数を定義する際にデフォルト値を設定すればエラーは起こりません。


list(tuple)やdictの中身を引数として渡すには

ここからは、可変長引数を使っていますが、あまり可変長引数とは関係なく、基礎の話です。

普通に渡すと、


list_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)を各要素を引数として渡したい場合は


*list.

>>> print_parameters(*[True, 1,2,3,4,5], 6, length=6)

True 6
args = (1, 2, 3, 4, 5, 6)
kwargs = {}

このように、*listの前につけることでひとつひとつ渡すことができます。

次に、dictをkeyword引数として渡したい場合は


**dict.

>>> 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をすべて渡してくれます。


*dict.

>>> 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可変長引数はひとつの関数に各々ひとつしか書けない。