1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【python】list初期化の罠

Last updated at Posted at 2022-11-11

始めに

リスト型または辞書型のリストを作るとき、事前に要素数を決めて初期化する場合があります。
例えば、辞書型の要素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])はすべて同じ値です。

1
1
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?