
【 Fluent Python + coding challenge 】List の List を作るときには要注意!! 投稿一覧へ戻る
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 という式で [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]]
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]]
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]] という結果にならなければいけません。
[[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]]
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]]
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]]
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 に追加しているんです。
気をつけましょう!
こちらの投稿にも興味があるかもしれません...
- 【Python 雑談・雑学 + coding challenge】Unicode の正規化処理 ( normalization ) を利用して、diacritical marks ( 発音区別符号 ) を取り除こう! テキスト解析の前処理としても重要です!
- 【Python 雑談・雑学 + coding challenge】文字列中の数字を抜き出して桁区切りをつけよう! 正規表現 (regular expression ) を使うと「えっ!?」っていうくらい簡単ですょ。lookahead と negative lookahead を使います。
- 【Python 雑談・雑学 + coding challenge】itertools モジュールの combinations() メソッドを自分で実装してみよう!
- 【Python 雑談・雑学 + coding challenge】sorted 組み込み関数の key パラメータをうまく使って、カスタムオブジェクトを簡単にソートしよう! __getitem__、__len__ 特殊関数 ( special methods, dunder methods ) を実装すれば立派なシーケンス ( sequence ) です
0 comments
コメントはまだありません。
コメントを追加する(不適切と思われるコメントは削除する場合があります)