関数[2]
引数について
前回は関数の定義や呼び出しについて説明しました。そして、最後に引数について実引数と仮引数の違いを補足として説明しました。今回は、引数の色々な定義の仕方について説明していきます。具体的には、位置引数、キーワード引数、デフォルト引数です。これらを使いこなせると、プログラミングの質が上がります。
位置引数
位置引数とは、先頭から順に対応する位置の仮引数にコピーされる引数のことです。サンプルを見ましょう。
>>> def calcBMI(weight, height): ... return weight / ((height/100)**2) ... >>> calculateBMI(60.0, 180.0) 18.51851851851852
calcBMI()関数は、引数に体重[kg]と身長[cm]を受け取り、BMIを計算して結果を返します。それぞれ先頭から順に実引数が仮引數に代入(60がweight、180がheight)されているのが分かるとお思います。
キーワード引数
先程の例のcalcBMI()関数は、heightとweightを引数にとりましたが、引数を誤って逆に代入してしまうことがあるかもしれません。このような位置引数によるミスを避けるためにキーワード引数を使います。キーワード引数とは仮引数の名前を指定して実引数を代入する方法です。
>>> calcBMI(weight=60.0, height=180) 18.51851851851852 >>> calcBMI(height=180, weight=60) 18.51851851851852
calcBMI()関数は先程定義したものです。キーワード引数を使うことにより、どのような順番で代入しても正しい値が計算されていることがわかります。位置引数で値を代入するときに間違えてしまいそうな時にはキーワード引数を使うと良いです。
位置引数とキーワード引数
位置引数とキーワード引数を一緒に使う場合は、位置引数を先に指定する必要があります。
>>> def light(red, yellow, green): ... if red: ... print("stop") ... ^C KeyboardInterrupt >>> def calc(first, second, third): ... return first / second + third ... >>> calc(10, third=4, second=2) 9.0 >>> calc(10, 2, 4) 9.0 >>> calc(third=10, 2, 4) File "<stdin>", line 1 SyntaxError: positional argument follows keyword argument
位置引数とキーワード引数を一緒に使うことができました。しかし、最後の関数呼び出しを見てわかるように、キーワード引数が先にあると例外を発生します。
デフォルト引数
仮引数の中には、ほとんどの場合は同じ値を使うけどたまに変えたいという場合もあるでしょう。そのような場合はデフォルト引数が便利です。デフォルト引数は、デフォルト値を関数定義の時に定義することにより、関数呼び出しの時に対応する引数が与えられなかった時に使われます。
>>> def calcCircumference(r, pi=3.14): ... return 2 * pi * r ... >>> calcCircumference(3.0) 18.84 >>> calcCircumference(3.0, pi=3) 18.0 >>> calcCircumference(pi=3.0, r=3) 18.0
calcCircumference()関数を定義しました。定義時にpiにデフォルト値(今回は3.14)を与えています。関数を呼び出す時に、pi引数を指定しないと3.14の値が使われていることがわかります。また、pi引数を指定した時はきちんと指定した値で計算されていることがわかります。
位置引数のタプル化
print()関数のように可変個の実引数を処理できる関数書きたいときなどに位置引数のタプル化を利用します。位置引数をタプル化するにはアスタリスク("*")を使います。関数の中で仮引数の一部として"*"を使うことにより、可変個の位置引数をタプルにまとめてその仮引数にセットすることができます。
>>> de print_args(*args): ... print("Args:", args) ... >>>printArgs() Args: () >>> def four(): ... return 4 ... >>> printArgs(1, 'two', "three", four()) Args: (1, 'two', 'three', 4) >>> def printArgs_2(first, second, *args): ... print("Arg1 is:", first) ... print("Arg2 is:", second) ... print("Other:", args) ... >>> printArgs_2(1, "two", 'three', four()) Arg1 is: 1 Arg2 is: two Other: ('three', 4)
最初の例のように実引数を与えないで呼び出すと、*argsには何も代入されず空タプルとなります。2番目の例のように使うことにより、可変個の引数を受け付けています。引数には何を与えてもかまいません。最後の例のようにすると、必須の引数(今回は"first"と"second")以外の全ての位置引数を1つにまとめることができます。"*"を使うとき、仮引数の前では"*"を書きますが、関数の中で呼び出したりする時には書きません。また、変数名には一般的な慣習として"args"を使うことが多いです。
キーワード引数の辞書化
位置引数のタプル化があるなら、キーワード引数の辞書化もありますよね。キーワード引数の辞書化には、2つのアスタリスク("**")を使い、それによりキーワード引数を1個の辞書にまとめることができます。引数の名前は辞書のキー、引数の値は辞書の値になります。
>>> def print_kwargs(**kwargs): ... print("Kwargs:", kwargs) ... >>> print_kwargs() Kwargs: {} >>> print_kwargs(one='1', two='2', three='3') Kwargs: {'one': '1', 'two': '2', 'three': '3'}
最初の例のように何も与えられない場合は、空辞書になります。2番目の例のように実引数をキーワード引数として関数を呼び出すと、結果のように辞書として表示されます。仮引数の前では、"*"を書きますが、関数内などでは"*"を書きません。また、変数名はkwargsを用いるのが一般的です。
タプル化と辞書化
タプル化と辞書化を同時に使う場合は、"args"・"*kwargs"の順に指定しなければならない。
>>> def print_all(*args, **kwargs): ... print("Args:", args) ... print("Kwargs:", kwargs) ... >>> print_all(1, 2, 3, one="eins", two="zwei", three="drei") Args: (1, 2, 3) Kwargs: {'one': 'eins', 'two': 'zwei', 'three': 'drei'}
最後に
お疲れ様でした。次回は名前空間の話をしたいと思います。