Quantcast
Viewing all articles
Browse latest Browse all 757

[Python]enumを使って多次元配列をするときの注意点

Background paizaスキルチェック のある問題を解いていたときに、2次元配列を使ってある区画の範囲に色を塗るといった処理が必要となりました。そこで各要素を列挙型を使ってみたのですが思った処理結果が出なかったので紹介します。 Initialize ここで色の列挙型と区画を初期化してみます。 class Color(Enum): WHITE = 0 RED = 1 GREEN = 2 BLUE = 3 # width:5 height:4 の2次元配列を作る mat = [[Color.WHITE] * 4] * 5 for r in mat: for c in r: print(c.name, end=" ") print("\n") WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE WHITE Issue 上記で設定した区画から (LEFT, TOP) = (2,2) (RIGTH, BOTTOM) = (3,4) の部分に赤色を塗りたい場合、 for r in range(1,4): for c in range(1,3): mat[r][c] = Color.RED WHITE RED RED WHITE WHITE RED RED WHITE WHITE RED RED WHITE WHITE RED RED WHITE WHITE RED RED WHITE なぜか2列目と3列目が全色赤になって1行目と5行目も塗ってしまいます。 WHY? てことで、各要素と各行のオブジェクトIDを出力してみます。 mat = [[Color.WHITE] * 4] * 5 for r in mat: for c in r: print(id(c)) print("[List]:{}".format(id(r))) 140539104199104 140539104199104 140539104199104 140539104199104 [List]:140539104158848 140539104199104 140539104199104 140539104199104 140539104199104 [List]:140539104158848 140539104199104 140539104199104 140539104199104 140539104199104 [List]:140539104158848 140539104199104 140539104199104 140539104199104 140539104199104 [List]:140539104158848 140539104199104 140539104199104 140539104199104 140539104199104 [List]:140539104158848 リストに同一のIDが振られています。 おそらくですが、[[(obj)] * num ] * num にすると列ごとのコピーは浅いコピーと判断されるみたいです。 浅いコピーについてですが公式では 浅いコピー (shallow copy) は新たな複合オブジェクトを作成し、その後 (可能な限り) 元のオブジェクト中に見つかったオブジェクトに対する 参照 を挿入します。となっていて要素自体を完全にコピーしておらずリンクだけが複製されています。 Solution pattern 1 python標準を使う場合は下記の通り。これで各行のリストのオブジェクトIDが重複しないので上記のような色を塗っても他の行には影響しないです。 mat = [] for r in range(5): #各行を作成 row = [] for c in range(4): row.append(Color.WHITE) mat.append(row) pattern 2 numpyを使う場合です。 np.arrayにラッピングします。 おそらくですがpaizaでスキルチェックしたい場合は使えないと思います。 import numpy as np mat = np.array([[Color.WHITE] * 4]*5) output pattern1とpattern2のどちらで設定しても下記の結果が出力されると思います。 for r in range(1,4): for c in range(1,3): mat[r][c] = Color.RED for r in np_mat: for c in r: print(c.name, end=" ") print("\n") WHITE WHITE WHITE WHITE WHITE RED RED WHITE WHITE RED RED WHITE WHITE RED RED WHITE WHITE WHITE WHITE WHITE Reference Python公式 enum Pythonのcopyとdeepcopyについて

Viewing all articles
Browse latest Browse all 757

Trending Articles