fluent_python

【 Fluent Python + coding challenge 】List の List を作るときには要注意!! 投稿一覧へ戻る

Tags: challenge , python , fluent

Published 2020年11月23日17:16 by T.Tsuyoshi

問題 ( 制限時間: 5 分 ):


[1] * 3 という式で [1, 1, 1] というリストを取得することが出来ます。


では、[[1, 1, 1], [1, 1, 1], [1, 1, 1]] という list の list を取得するための式を記述してください。



簡単ですね。


[1] * 3 を3つ含むリストを作ればいいんです。


nest_list = [[1] * 3] * 3


print(nest_list)

# [[1, 1, 1], [1, 1, 1], [1, 1, 1]]



はい、出来ました。


それでは皆さん、ごきげんよう。


って、本当に大丈夫ですか?


今作ったリストのリストの [1][2] の要素の値を変えてみましょう。


nest_list[1][2] = 3

print(nest_list)

# [[1, 1, 3], [1, 1, 3], [1, 1, 3]]



???


これが本当に望んでいる結果ですか?


[[1, 1, 1], [1, 1, 3], [1, 1, 1]]、<= こうなってほしいんじゃないですか?


では、やり直しです。


問題 ( 制限時間: 5 分 ):


[[1, 1, 1], [1, 1, 1], [1, 1, 1]] という list の list を取得するための式を記述してください。


出来上がったリストのリストの [1][2] の要素に 3 を代入した場合、


[[1, 1, 1], [1, 1, 3], [1, 1, 1]] という結果にならなければいけません。



リスト内包表記 ( list comprehension ) を利用しましょう。


nest_list = [[1] * 3 for _ in range(3)]


print(nest_list)

# [[1, 1, 1], [1, 1, 1], [1, 1, 1]]


nest_list[1][2] = 3

print(nest_list)

# [[1, 1, 1], [1, 1, 3], [1, 1, 1]]



大丈夫ですね。


実は、最初の間違えを for 文で書き直すと、次のようなことをやっていることと同じなんです。


inner_list = [1] * 3
outer_list = []
for _ in range(3):
outer_list.append(inner_list)


print(outer_list)

# [[1, 1, 1], [1, 1, 1], [1, 1, 1]]


outer_list[1][2] = 3


print(outer_list)

# [[1, 1, 3], [1, 1, 3], [1, 1, 3]]



つまり、外側のリストの中に含まれている [1, 1, 1] というリストの実体は 1 つだけで、外側のリストはそのリストへの参照を 3 つ含んでいるだけなんですね。


これに対して、正解の書式を for 文を利用して書き直してみると次のようになります。


outer_list = []
for _ in range(3):
inner_list = [1] * 3
outer_list.append(inner_list)


print(outer_list)

# [[1, 1, 1], [1, 1, 1], [1, 1, 1]]


outer_list[1][2] = 3


print(outer_list)

# [[1, 1, 1], [1, 1, 3], [1, 1, 1]]



その都度新しい [1, 1, 1] というリストを作成して outer_list に追加しているんです。


気をつけましょう!

この投稿をメールでシェアする

0 comments

コメントはまだありません。

コメントを追加する(不適切と思われるコメントは削除する場合があります)