複合的な、しかもそれぞれが分かりづらい理由で挙動を追いづらくなっています。
- ループ中で定義した関数には注意
次のように、イメージと異なる結果になります。
Python
1funcs = []
2for i in range(3):
3 funcs.append(lambda: print(f'i = {i}'))
4
5for func in funcs:
6 func()
実行結果 Wandbox
次のように回避する方法が知られています。
Python
1for i in range(3):
2 funcs.append(lambda e=i: print(f'e = {e}')) # 外部変数iを直接使わない
参考: ループの中で異なる値で定義されたラムダ式が、同じ値を返すのはなぜですか?
- リストをデフォルト引数にしない
Python独特の挙動で、嵌りやすいです。
Python
1def func(e, lst=[]):
2 lst.append(e)
3 print(lst)
4
5func(0)
6func(1)
7func(2)
実行結果 Wandbox
次のように回避する方法が知られています。
Python
1def func(e, lst=None): # デフォルト引数をNoneにする
2 if lst is None:
3 lst = []
4
5 lst.append(e)
6 print(lst)
参考: なぜオブジェクト間でデフォルト値が共有されるのですか?
トレース
一つ目のコード
Python
1list=[]
2for i in range(3):
3 list.append(lambda x:x+i-1)
4 # ループ終了時点で全要素が lambda x: x+2-1 になっている
5
6sum=0
7
8for a in list: # リスト長は3
9 sum += a(1) # a(1) は常に 1+2-1 = 2 を返す
10print(sum) # 3回足したら 3x2 = 6
二つ目のコード・前半
Python
1def abc(price,list=[]):
2
3 for i in range(3):
4 list.append(lambda x:x+i-1)
5 # 全要素が lambda x: x+2-1
6
7 sum=0
8
9 for a in list:
10 sum += a(price) # a(0) は常に 0+2-1 = 1 を返す
11
12 return sum # 3回足したら 3
13
14print(abc(0))
二つ目のコード・後半
Python
1def abc(price,list=[]): # 関数突入時点で list = [lambda x: x+2-1 が3つ]
2
3 for i in range(3):
4 list.append(lambda x:x+i-1)
5 # 全要素が lambda x: x+2-1
6
7 sum=0
8
9 for a in list: # リスト長は6
10 sum += a(price) # a(1) は常に 1+2-1 = 2 を返す
11
12 return sum # 6回足したら 12
13
14print(abc(1))
解決案
少なくとも今回のコードについては、あまり難しく考える必要は無いでしょう。
Python
1def abc(price):
2 ret = 0
3 for i in range(3):
4 ret += price + i - 1
5
6 return ret
あるいは
Python
1def abc(price):
2 return sum(
3 price + i - 1 for i in range(3)
4 )
更には
Python
1def abc(price):
2 n = 3
3 return n*(price-1) + (n*(n-1)//2)
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。