始めに
リスト型または辞書型のリストを作るとき、事前に要素数を決めて初期化する場合があります。
例えば、辞書型の要素6個のリスト
を作りたいときに、主に以下のやり方がありますが、場合によっては罠にはまります。
書き方1
書き方1
list1 = []
for i in range(6):
list1.append({"age":1})
print(list1)
書き方2
書き方2
list2 = [{"age":1}]*20
print(list2)
上記書き方の出力は同じになります。
実行結果
[{'age': 1}, {'age': 1}, {'age': 1}, {'age': 1}, {'age': 1}, {'age': 1}]
ただし、書き方2はバグの引き金になってしまう可能性があります。
下記を実行してみてください。
listの1要素を変更
list2[0]["age"] = 9
print(list2)
結果は想定と違って、以下となります。1要素目だけでなく、全要素が更新されてしまったようです。
実行結果
[{'age': 9}, {'age': 9}, {'age': 9}, {'age': 9}, {'age': 9}, {'age': 9}]
一方、
listの1要素を変更
list1[0]["age"] = 9
print(list1)
結果は想定どおり、1要素目だけ更新されています。
実行結果
[{'age': 9}, {'age': 1}, {'age': 1}, {'age': 1}, {'age': 1}, {'age': 1}]
原因
実は、書き方2で初期化したリストの要素は、すべて同一オブジェクトです。
検証:
要素比較
print(list2[0] == list2[1])
print(list2[0] is list2[1])
実行結果
実行結果
True
True
一方、list1の各要素はそれぞれ違うオブジェクトとなります。
要素比較
print(list1[0] == list1[1])
print(list1[0] is list1[1])
実行結果
実行結果
True
False
補足
初期化2を使ってバグを作ってしまったので、検証してみました。
ちなみに、当たり前ですが、id(list2[x])はすべて同じ値です。