switch (select) 構文のないPythonではその代わりに辞書を使うことがありますが,
その実行時間に関する注意です.
結論
-
関数自体を入れる:{ key: func }
- 短時間で済む
- 実行されるのはキーによって選択された関数のみ
-
関数の返り値を入れる:{ key: func() }
- 余計な時間がかかる
- 全ての関数が一旦実行され,その返り値が入る
関数の引数が異なる場合は,
- 予め関数の引数に
( *args, **kwargs )
を用意しておきその差を吸収する - 与える引数自体も辞書にしてしまう
- e.g.
dict_kwargs = { 1: { 'arg1': arg1 }, 2: { 'arg2': arg2 } }
- e.g.
という方法が考えられます.
例
以下の2つの関数を場合分けして実行する場合を考えます.
(実行時間が知りたいので遅くなるような書き方をしています.)
def myfunc1():
nx, ny = 50, 40
arr = np.empty( ( nx, ny ) )
for iy in range( ny ):
for ix in range( nx ):
arr[ix,iy] = ix * ix + iy * iy
return arr
def myfunc2():
nx, ny = 50, 40
arr = np.empty( ( nx, ny ) )
for iy in range( ny ):
for ix in range( nx ):
arr[ix,iy] = 1
return arr
その上で,以下の3通りの実行方法にかかる時間を計測しました(JupyterLabの%%timeit使用,下はmyfunc1のみ).
# 直接関数を実行
myfunc1()
# { key: func } 型の辞書から実行
key = 1
dict_func = { 1: myfunc1, 2: myfunc2 }
dict_func[ key ]()
# { key: func() } 型の辞書から実行
dict_return = { 1: myfunc1(), 2: myfunc2() }
dict_return[ key ]
結果は以下の通りでした.{ key: func() } 型では,両方の関数が実行される時間に近い時間がかかっていることが分かります.
# 直接実行
1: 488 µs ± 26.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
2: 286 µs ± 925 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
# { key: func } 型
1: 461 µs ± 332 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
2: 298 µs ± 22.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
# { key: func() } 型
1: 763 µs ± 3.96 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
2: 771 µs ± 31.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)