pythonでインスタンスのリストを作り、インスタンス関数に対して同一変数を与える方法等。
結論は、mapとlambdaを使うと便利ということ。
例として次のような、クラスを定義する。
class myclass:
def __init__(self,val):
self.val=val
def func(self,val):
return self.val==self.val
次のように動作する。
o=myclass(0)
o.func(0) → True
o.func(1) → False
これを、インスタンスのリストとする。
ol=[myclass(1),myclass(2),myclass(3)]
olのインスタンス全てに対してfunc(x)を呼ぶ時、forを使って次のように書ける。
for o in ol:
o.func(x)
上のままでは全く意味のない動作である。
(1)全ての結果をリストとして得たい場合、例えば次のように書ける。
rl=[]
for o in ol:
rl.append(o.func(x))
(2)一つでもTrueを返す場合何某かの処理をするという場合、例えば次のように書ける。
for o in ol:
if o.func(x):
<何某かの処理>
break
(breakが無ければ、Trueが複数返る場合はその回数だけ処理を行う。)
(3)全てがTrueの場合に処理する場合、例えば次のように書ける。
flag=True
for o in ol:
if not(o.func(x)):
flag=False
break
if flag:
<何某かの処理>
ここからが本題。
mapとlambdaを使用すると、forを使わなくても全てのインスタンスについてfuncを呼び出せる。
map(lambda o: o.func(x), ol)
以下は、それぞれ上記の例と同じ動作をするものである。
(1)
rl=list(map(lambda o: o.func(x), ol))
(2)
if any(map(lambda o: o.func(x), ol)):
<何某かの処理>
(3)
if all(map(lambda o: o.func(x), ol)):
<何某かの処理>
anyやallとmapを組み合わせる場合、
anyでは最初にTrueが返った段階で、以降のインスタンスのfunc(x)は実行されない。
allでは最初にFalseが返った段階で、以降の(略)。
これは、mapが生成される段階では、まだmapされた関数は実行されないということである。
最初の例のようにmapをリスト化する場合、その段階で全てに対してfunc(x)が実行される。
(追記)
mapとlambda以外に、リスト内包表記を使うこともできる。
(1)については、リスト内包表記を使うと、次のように書ける。
rl=[o.func(x) for o in ol]
同様に(2)は、
if any([o.func(x) for o in ol]):
<何某かの処理>
(3)は、
if all([o.func(x) for o in ol]):
<何某かの処理>
ただし、(2)と(3)は全てのインスタンスのfunc(x)が実行されることになる。
(1)についてはリスト内包表記の方が処理が速いようだ。
したがって、単純にリストを生成する場合、リスト内包表記の方が適しているだろう。
(2)と(3)のようにallやanyと組み合わせる場合、func(x)の処理が重くなると、mapとlambdaが有利になる・・・こともあると思う。
(anyの中でTrueが出る可能性が高い場合や、allでFalseの可能性が高い場合)