0
0

Python:二次元リストを作る際の注意点

Last updated at Posted at 2024-06-03

二次元リストを作る際の注意点

皆さん、二次元リストを書く際、どのように記述していますか?
恐らく多くの人が以下のようにfor文を用いて記述していると思います。

fields=[[0 for _ in range(4)] for _ in range(4)]
print(fields)
# [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

ただ、二次元リストを作るだけなら以下のようにも記述できますよね。

fields=[[0]*4]*4
print(fields)
# [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

リストの中身にもよりますが、状況によっては下のコードの方が、短く済みそうですよね。
しかし、実は下のコードは二次元リストとしての役割を果たしていません。
試しにリストの中身を更新してみます。
まずは、for文で書いた二次元リストから更新します。

fields=[[0 for _ in range(4)] for _ in range(4)]
print(fields)
# [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

fields[0][1]=1
print(fields)
# [[0, 1, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

次に、「*」を使ったリストを更新してみます。

fields=[[0]*4]*4
print(fields)
# [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

fields[0][1]=1
print(fields)
# [[0, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0]]

指定したのは[0][1]のみなのに、実際には[0:][1]が更新されています。
理由は、オブジェクトのidにあります。

fields=[[0 for _ in range(4)] for _ in range(4)]
print(fields)
# [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

print(id(fields[0]))
print(id(fields[1]))
# 2754287228736
# 2754287228864

本来は、このように同じ二次元リストに存在していても行ごとにidが違うはずです。
では、「*」の二次元リストはどうでしょうか。

fields=[[0]*4]*4
print(fields)
# [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

print(id(fields[0]))
print(id(fields[1]))
# 2754288924672
# 2754288924672

同じidが出力されています。
普段、私たちが変数を使う場合、コンピュータ側はidで指定しています。
なので、今回のような現象が起きてしまうわけです。


id関連の落とし穴はよくあるので、頭の片隅にでも置いていただければと思います。

0
0
1

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
0
0