pythonにて、パラメータ、戻り値の数が異なっても同じインタフェースで呼び出したい場合があります。同一インタフェースで呼び出す方法を検討します。
関数
以下の関数を考えます。
def func1(x, a=2, b=3, c=4):
print("IN x=", x, "a=", a, "b=", b, "c=", c)
x *= 2
a *= 2
b *= 2
c *= 2
print("OUT x=", x, "a=", a, "b=", b, "c=", c)
return x, a, b, c
与えられたパラメータを2倍して返す関数です。
$=$で既定値を指定しているパラメータは省略可能パラメータ、既定値を指定しない場合は、必須のパラメータになります。
関数のパラメータ
通常の呼び出し
関数の呼び出し方法は、パラメータの順序で呼び出す方法、省略可能なパラメータに限られますが、パラメータ名を指定して呼び出す方法があります。
# パラメータ順
func1(10,20,30)
結果
IN x= 10 a= 20 b= 30 c= 4
OUT x= 20 a= 40 b= 60 c= 8
# パラメータ名指定
func1(10, a=20, c=40)
結果
IN x= 10 a= 20 b= 3 c= 40
OUT x= 20 a= 40 b= 6 c= 80
# 両方
func1(10, 20, c=40)
結果
IN x= 10 a= 20 b= 3 c= 40
OUT x= 20 a= 40 b= 6 c= 80
リスト、辞書を利用した呼び出し
順序で呼び出す場合は、リストを利用できます。タプルでも可能です。
$*$をつけて呼び出します。
# パラメータ順(リスト)
param = [20,30]
func1(10, *param)
結果
IN x= 10 a= 20 b= 30 c= 4
OUT x= 20 a= 40 b= 60 c= 8
パラメータ名付きで呼び出す場合は、辞書を利用できます。
$**$をつけて呼び出します。
# パラメータ名指定(辞書)
param = {"a":20, "c":40}
func1(10, **param)
結果
IN x= 10 a= 20 b= 3 c= 40
OUT x= 20 a= 40 b= 6 c= 80
通常の呼び出しと同じになりました。
両方の場合です。
# 両方
paraml = [20]
paramd = {"c":40}
func1(10, *paraml, **paramd)
結果
IN x= 10 a= 20 b= 3 c= 40
OUT x= 20 a= 40 b= 6 c= 80
リスト、辞書で呼び出すことが可能なことがわかりました。
関数の戻り値
関数の戻り値は、カンマで区切って複数指定することが可能です。戻り値は、タプルで返却されます。
print(type(func1(10)))
結果
IN x= 10 a= 2 b= 3 c= 4
OUT x= 20 a= 4 b= 6 c= 8
<class 'tuple'>
通常の受け取り方
戻り値を順に受け取ります。
x, a, b, c = func1(10)
print(x, a, b, c)
結果
IN x= 10 a= 2 b= 3 c= 4
OUT x= 20 a= 4 b= 6 c= 8
20 4 6 8
特定の戻り値のみ受け取る場合は、受け取らないパラメータは、'_'とします。
_, a, _, _ = func1(10)
print(a)
結果
IN x= 10 a= 2 b= 3 c= 4
OUT x= 20 a= 4 b= 6 c= 8
4
別の方法としては、戻り値はタプルのため、パラメータ番号を指定して取得できます。
a = func1(10)[1]
print(a)
結果
IN x= 10 a= 2 b= 3 c= 4
OUT x= 20 a= 4 b= 6 c= 8
4
リストを利用した受け取り方
リストは、残りのパラメータをすべて取得する場合に利用します。
$*$をつけます。
x, *oparam = func1(10)
print(x)
print(oparam)
結果
IN x= 10 a= 2 b= 3 c= 4
OUT x= 20 a= 4 b= 6 c= 8
20
[4, 6, 8]
辞書を利用した受け取り方
戻り値に名前を付けて返却する方法が分かりませんでした。
戻り値自体を辞書にしてみました。
def func1d(x, a=2, b=3, c=4):
print("IN x=", x, "a=", a, "b=", b, "c=", c)
x *= 2
a *= 2
b *= 2
c *= 2
print("OUT x=", x, "a=", a, "b=", b, "c=", c)
return x, {"a":a, "b":b, "c":c}
戻り値を確認してみます。
x, oparam = func1d(10)
print(x)
print(oparam)
結果
IN x= 10 a= 2 b= 3 c= 4
OUT x= 20 a= 4 b= 6 c= 8
20
{'a': 4, 'b': 6, 'c': 8}
異なるパラメータ、戻り値の関数の同一インタフェースによる呼び出し
パラメータ、戻り値の異なる関数を同一インタフェースで呼び出すことを考えます。
以下の2つの関数で考えます。
def func1(x, a=2, b=3, c=4):
print("IN x=", x, "a=", a, "b=", b, "c=", c)
x *= 2
a *= 2
b *= 2
c *= 2
print("OUT x=", x, "a=", a, "b=", b, "c=", c)
return x, a, b, c
def func2(x, a=2, d=5):
print("IN x=", x, "a=", a, "d=", d)
x *= 3
a *= 3
d *= 3
print("OUT x=", x, "a=", a, "d=", d)
return x, a, d
パラメータ位置固定
パラメータ位置を固定できる場合の呼び出しは、リストを利用して行います。
def call_funcl(func, x, *param):
x, *param = func(x, *param)
return x, param
func1, func2両方の関数を呼び出してみます。
x, param = call_funcl(func1, 10, 20, 30)
print(x)
print(param)
結果
IN x= 10 a= 20 b= 30 c= 4
OUT x= 20 a= 40 b= 60 c= 8
20
[40, 60, 8]
x, param = call_funcl(func2, 10, 20, 30)
print(x)
print(param)
結果
IN x= 10 a= 20 d= 30
OUT x= 30 a= 60 d= 90
30
[60, 90]
両方の関数が呼び出せました。
3回連続で呼び出してみます。
x, param = call_funcl(func1, 10, 20, 30)
x, param = call_funcl(func1, x, *param)
x, param = call_funcl(func1, x, *param)
結果
IN x= 10 a= 20 b= 30 c= 4
OUT x= 20 a= 40 b= 60 c= 8
IN x= 20 a= 40 b= 60 c= 8
OUT x= 40 a= 80 b= 120 c= 16
IN x= 40 a= 80 b= 120 c= 16
OUT x= 80 a= 160 b= 240 c= 32
パラメータ名指定
辞書を利用します。
以下の2つの関数で考えます。
def func1d(x, a=2, b=3, c=4):
print("IN x=", x, "a=", a, "b=", b, "c=", c)
x *= 2
a *= 2
b *= 2
c *= 2
print("OUT x=", x, "a=", a, "b=", b, "c=", c)
return x, {"a":a, "b":b, "c":c}
def func2d(x, a=2, d=5):
print("IN x=", x, "a=", a, "d=", d)
x *= 3
a *= 3
d *= 3
print("OUT x=", x, "a=", a, "d=", d)
return x, {"a":a, "d":d}
2つの関数を呼び出す関数を考えます。
def call_funcd(func, x, **param):
x, param = func(x, **param)
return x, param
実際に呼び出してみます。
x, param = call_funcd(func1d, 10, a=20, c=40)
print(x)
print(param)
結果
IN x= 10 a= 20 b= 3 c= 40
OUT x= 20 a= 40 b= 6 c= 80
20
{'a': 40, 'b': 6, 'c': 80}
x, param = call_funcd(func2d, 10, d=50)
print(x)
print(param)
結果
IN x= 10 a= 2 d= 50
OUT x= 30 a= 6 d= 150
30
{'a': 6, 'd': 150}
両方呼び出せました。
3回連続して呼び出してみます。
x, param = call_funcd(func1d, 10, a=20, c=40)
x, param = call_funcd(func1d, x, **param)
x, param = call_funcd(func1d, x, **param)
結果
IN x= 10 a= 20 b= 3 c= 40
OUT x= 20 a= 40 b= 6 c= 80
IN x= 20 a= 40 b= 6 c= 80
OUT x= 40 a= 80 b= 12 c= 160
IN x= 40 a= 80 b= 12 c= 160
OUT x= 80 a= 160 b= 24 c= 320
なかなかおもしろいですね。
パラメータを順序で受け取る場合は、リストを、名前付きで受け取る場合は、辞書を利用すること、関数の戻り値はタプルであることを覚えておけば、迷わずに対応できます。