LoginSignup
0
0

More than 5 years have passed since last update.

パラメータが異なる関数のリストを作りたい

Last updated at Posted at 2019-03-04

事象

Pythonで、ある関数のパラメータの値が一部異なる関数のリストを作りたい。
こんな感じ。

f = lambda a, x: a * x
f_list = [
    lambda x: f(0, x),
    lambda x: f(1, x),
    lambda x: f(2, x)
]

で、そのまま次のように書いてみる。

f = lambda a, x: a * x
f_list = [lambda x: f(a, x) for a in range(3)]

すると、 f_list の要素がすべて lambda x: f(2, x) になってしまった。
2行目の a の部分は0, 1, 2と代入されたものにしたい。

検証

なぜ同じ関数になってしまうのか確かめるために、 f を関数で書き直し、オブジェクトのidをprintしてみる。

def f(a, x):
    print(id(a))
    return a * x

f_list = [lambda x: f(a, x) for a in range(3)]

f_list[0](1)
f_list[1](1)
f_list[2](1)

この結果は

id(a) = 140735854982000
id(a) = 140735854982000
id(a) = 140735854982000

a のidはすべて同じ、つまり、同じオブジェクトということ。
ラムダ式の中でのパラメータ a は、同じ参照になってしまうようである。

対策

同じ参照にならないように、 functoolspartial を用いる。

from functools import partial

def f(a, x):
    print('id(a) = ' + str(id(a)))
    return a * x

f_list = [partial(f, a) for a in range(3)]

f_list[0](1)
f_list[1](1)
f_list[2](1)

この結果は

id(a) = 140735854981936
id(a) = 140735854981968
id(a) = 140735854982000

異なるidになった。
これは、もちろん f をラムダ式に戻しても問題なし。

f = lambda a, x: a * x
f_list = [partial(f, a) for a in range(3)]

まとめ

関数を複製したい場合は、 functools.partial を用いればよい。

0
0
1

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
0
0