【Python・アンチパターン】多次元リストの初期化
多次元リストの初期化時に演算子*
を利用すると、想定外の動きをするので、アンチパターンとして記載。
目的
初期化された多次元リストを生成する。
アンチパターン
演算子*
を用いて、初期化された多次元リストを生成すると、想定外の挙動をする。
具体的な事象
# NG b_list = [[0]]*3 print(b_list) #[[0],[0],[0]] b_list[0].append(1) print(b_list) #[[0,1],[0,1],[0,1]]
演算子
*
を用いて、初期化された多次元リストを生成。その後、生成されたリストの先頭要素だけに
1
を追加すると、同処理が何故か全要素に適用される。
解説
演算子*
について
演算子*
は、a. (数値, 数値)
とb. (シークエンス, 整数)
のように引数の型によって、以下のように作用が異なる。
- (数値, 数値):数値を共通の型に変換した後、掛け合わせた結果を返す。
- (シークエンス, 整数):シークエンスを整数回を繰り返した結果を返す。 ただし、整数が負の値の場合、空のシークエンスを返す。
b. (シークエンス, 整数)
の処理内容について
シークエンス*整数
の返す結果は、元のシークエンス
上のオブジェクトのコピーではなく、同じオブジェクトへの参照のコピーである。
解決策
単純にfor文で繰り返すことで解決。
# OK a_list = [[0] for _ in range(3)] print(a_list) #[[0],[0],[0]] a_list[0].append(1) print(a_list) #[[0,1],[0],[0]]