LoginSignup
48
43

More than 5 years have passed since last update.

可変長引数

Last updated at Posted at 2015-10-17

可変長引数

可変長引数は、その名の通り引数の長さを自由に変えられる引数。
なので、どんな数の引数を渡しても対応できる関数となるわけです。
関数の引数に*または**をつけると定義できます。
可変長引数は各々ひとつづつしか定義できません。
※ややこしかったので、うまくまとまってないかもしれないです。
まず、簡単なサンプルから

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

48
43
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
48
43