質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

3回答

667閲覧

pythonの2次元配列についての質問です.

tomou

総合スコア2

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/07/14 07:59

前提・実現したいこと

pythonの2次元配列の作成についての質問です.
ソースコードにあるように a ,b ,c 以下のように出力されます
aの方法はa[0][1]を変更すると全てに適応されます
bの方法はa[0][1]だけをしっかり変更してくれます
cの方法はa[0]だけをしっかり変更してくれます

なぜaは全てに適応されてしまうんでしょうか?

逆にcではなぜうまくいくのでしょうか?

気になって夜も寝られません、よろしくお願いします。

該当のソースコード

python

1a=[[0,0]]*5 2a[0][1]='x' 3print(a) 4#[[0, 'x'], [0, 'x'], [0, 'x'], [0, 'x'], [0, 'x']] 5 6b=[] 7for i in range(5): 8 b.append([0,0]) 9b[0][1]='x' 10print(b) 11#[[0, 'x'], [0, 0], [0, 0], [0, 0], [0, 0]] 12 13c=[0]*5 14c[0]='a' 15print(c) 16#['a', 0, 0, 0, 0] 17 18

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

y_waiwaiさんの回答へのコメントにひっかかったので、書いてみます。

ではcが['a', 'a', 'a', 'a', 'a']ではなく['a', 0, 0, 0, 0]と

きちんと適応されるのはなぜでしょうか、同じ * を
しているのに['a', 'a', 'a', 'a', 'a']のようにならないのは
なぜでしょうか?

a=[[0,0]]*5c=[0]*5 で外側のリストに対して同じ立場にあるのは、[0,0]0 です。

a で a[0] = 'x' としていれば、['x', [0, 0], [0, 0], [0, 0], [0, 0]]となったはずです。

また、aでやっていることは、リストの内容であるところのリストa[0]の値そのものの変更です。そして、pythonではそのリスト(ここでは[0,0])を変更する方法が用意されていて、a[0][1]='x' => [0,0][1]='x' => [0,'x'] となっています。
cの0のリストも実はすべて同じ0が見えているのです。なので、その0そのものの値を変更する方法があれば、その方法を使ってその0の値を変更することができて、全ての0が変更されたのでしょうが、そのような方法はpythonに用意されていないのです。

投稿2021/07/14 11:35

編集2021/07/14 11:38
TakaiY

総合スコア12830

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tomou

2021/07/15 02:35

cについての詳しい言及ありがとうございます。 「a で a[0] = 'x' としていれば、['x', [0, 0], [0, 0], [0, 0], [0, 0]]となったはずです。  また、aでやっていることは、リストの内容であるところのリストa[0]の値そのものの変更です。」 とてもわかりやすく解説してくださり、ありがとうございます。 頂いた解答をヒントに自分でも手を動かして勉強させてもらいました。 「その0そのものの値を変更する方法があれば、その方法を使ってその0の値を変更することができて」 この文章からも気づきを得ることができました。ありがとうございます。
guest

0

公式ドキュメントのFAQにあるなぜ list 'y' を変更すると list 'x' も変更されるのですか? の一種です。

ここに書かれている説明の、xとyをa[0]とa[1]だとすれば、a[0][1]を変更したときにa[1][1]が変更されたように見えることがわかります。

つまり、a[0]、a[1]、a[2]、a[3]、a[4]はコピーではなく全く同じものなのです。

Pythonでは「全く同じ」と「同じようなもの」は区別しています。
XとYが「全く同じ」は X eq Y で、「同じようなもの」は X == Y です。

print(a[0] eq a[1])

を実行して確認してください。

  • 追加の説明です。

a=[[0,0]]*5 としたときにaを10個の要素を持つ二次元配列だと誤解する方もいらっしゃいますが、そうれは間違っています。
aは5個の要素を持つリストです。

python

1>>> a=[[0,0]]*5 2>>> print(len(a)) 35

この5個の要素はそれぞれPythonのオブジェクトです。
a=[[0,0]]*5 というのは以下と同じことをやっています。
b = [0, 0]
a = [b, b, b, b, b]
a[0] も a[1] も a[2] も a[3] も a[4] も b なのですべて同じなのです。

投稿2021/07/14 08:30

編集2021/07/14 13:33
ppaul

総合スコア24666

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tomou

2021/07/15 02:07

「コピーではなく全く同じもの」昨日copy deepcopy についての文章を読んでいたのでこの説明しっくりきました。ありがとうございます。 公式ドキュメントのリンクありがとうございます。 大変勉強になりました。
guest

0

a=[[0,0]]*5

ってのは、[0,0]を5つコピーしてくれる、んじゃなくて、
[0,0] のオブジェクトを5つコピーするだけ、ですね。
各要素は同じものを指してることになります
a[0] とa[1]と、、、a[4]は同じものを指してるがために、

a[0][1]='x'

では全要素変わってしまうんですね

投稿2021/07/14 08:07

y_waiwai

総合スコア87800

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tomou

2021/07/14 08:23

爆速解答ありがとうございます。 「[0,0]を5つコピーしてくれる、んじゃなくて、  [0,0] のオブジェクトを5つコピーするだけ」 aとbの違いは理解しました。 ではcが['a', 'a', 'a', 'a', 'a']ではなく['a', 0, 0, 0, 0]と きちんと適応されるのはなぜでしょうか、同じ * を しているのに['a', 'a', 'a', 'a', 'a']のようにならないのは なぜでしょうか?
y_waiwai

2021/07/14 08:35

ちゃんとappendで[0,0]を追加していってるんで、ちゃんとした2次元配列になってるってことですね んで、 c=[0]*5 は、0という(オブジェクトでなく)数字を5つコピーしてるんで、そういう結果になるってことですね
tomou

2021/07/15 02:06

「オブジェクトでなく 数字」 頂いた解答を手掛かりにググりながら理解できました。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問