5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

pythonで、パラメータ、戻り値の数の異なる関数を同一インタフェースで呼び出す方法

Posted at

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

なかなかおもしろいですね。
パラメータを順序で受け取る場合は、リストを、名前付きで受け取る場合は、辞書を利用すること、関数の戻り値はタプルであることを覚えておけば、迷わずに対応できます。

5
6
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
5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?