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

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

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

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

286閲覧

[Python3]リストで指定したインデックス以下全てに勝手に代入される。

hososo

総合スコア34

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

1クリップ

投稿2017/08/26 15:29

概要

Python3です。
リストで指定したインデックス以下に勝手に全て代入されてしまいます。
例えば li = [0,0,0,0,0] に対して li[2] = 1 とすると 結果が [1,1,1,0,0] となってしまうということです。

下記が問題のコードです。A_list[m] = copy_num の箇所が上記の例のようになってしまいます。
尚、未完のコードなので最後の方にエラーが出ますがそこは大丈夫です。。

コード

#coding:utf-8 num = [1,2,3,4,5] post_li = [] copy_num = num #[1,2,3,4,5] A_list = [0,0,0,0,0] m = 0 def jamaika(): global post_li global copy_num global A_list global m print('-------------') print(str(m)+"層") print("copy_num>>",end="") print(copy_num) print('m>>'+str(m)) A_list[m] = copy_num #問題のコード print("A_list>>",end="") print(A_list) for i in range(5-m): post_li.append(copy_num[i]) del copy_num[i] if m == 4: print("Last_post_li>>",end="") print(post_li) else: print("post_li>>",end="") print(post_li) m += 1 jamaika() m -= 1 jamaika()

実行結果

0層
copy_num>>[1, 2, 3, 4, 5]
m>>0
A_list>>[[1, 2, 3, 4, 5], 0, 0, 0, 0]
post_li>>[1]

1層
copy_num>>[2, 3, 4, 5]
m>>1
A_list>>[[2, 3, 4, 5], [2, 3, 4, 5], 0, 0, 0]
↑m>>1なので A_list[m] = copy_num は A_list[1] = copy_num となると思ったのですが何故か[0]まで代入されてしまいます。
post_li>>[1, 2]

2層
copy_num>>[3, 4, 5]
m>>2
A_list>>[[3, 4, 5], [3, 4, 5], [3, 4, 5], 0, 0]
※同様です。
post_li>>[1, 2, 3]

3層
copy_num>>[4, 5]
m>>3
A_list>>[[4, 5], [4, 5], [4, 5], [4, 5], 0]
※同様です。
post_li>>[1, 2, 3, 4]

4層
copy_num>>[5]
m>>4
A_list>>[[5], [5], [5], [5], [5]]
※同様です。
Last_post_li>>[1, 2, 3, 4, 5]

環境

関係あるか微妙ですが
OS:Windows8.1
エディタ:Eclipse NEON

検索や試行錯誤を繰り返したのですが解決に至らなかったのでここで質問させていただきます。
面倒な質問だと思われますがご教授よろしくおねがいします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

該当箇所を以下のように変更すると期待どおりの動きになるはずです

python

1A_list[m] = copy_num #問題のコード 23A_list[m] = copy_num[::] # copy_numをコピーした別のリストを入れてます

何が起きていたかというと、以下の例がわかりやすいと思います。
origin変数としてリストをつくり、それをa変数に代入し、a_listにaを複数格納しています。
このとき、originと全てのaは同じものを指しています。

python

1>>> origin = [1, 2, 3, 4, 5] 2>>> a = origin 3>>> a_list = (a, a, a, a, a) # originと全てのaは同じものを指している 4>>> a_list 5([1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5]) 6>>> origin[4] = 10000 7>>> a_list 8([1, 2, 3, 4, 10000], [1, 2, 3, 4, 10000], [1, 2, 3, 4, 10000], [1, 2, 3, 4, 10000], [1, 2, 3, 4, 10000]) 9>>>

リストだけではなく、ミュータブルなオブジェクトであれば同様のことが起きます。クラスのインスタンスや辞書でも同じです。
イミュータブルな、例えば数値等ではこれは起きません。(これは正確には、同名の変数を定義し直しているだけなので例としては不適切でした...)

python

1>>> origin = 1 2>>> a = origin 3>>> a_list = (a, a, a, a, a) 4>>> a_list 5(1, 1, 1, 1, 1) 6>>> origin = 10000 7>>> a_list 8(1, 1, 1, 1, 1) 9

ミュータブルやイミュータブル等の難しい言葉を使っていますが、よく使うものであればリスト、辞書、クラスのインスタンスあたりがミュータブルなので、他変数に代入したりリストに複数格納する際は少し気をつけてください。(特に、関数の引数にミュータブルなオブジェクトを渡す際はハマりポイントです)

一番上で変更したコードは、
list[:4]のようにリストのスライスをすると別のリストが作成され返されるんですが、それを応用し
list[::]のようにすることで中身が同じな、別のリストを作成しました。
他にもコピーを作る方法はいくつかあります。

python

1# リストのコピーを作る方法 2>>> a = [1, 2, 3] 3>>> b = list(a) 4>>> c = a.copy() 5>>> d = a[::] 6 7# id関数の値が違うならば、それらは別のオブジェクトと判断できます 8>>> id(a) 9140676014804168 10>>> id(b) 11140676014820232 12>>> id(c) 13140676014819720 14>>> id(d) 15140676014819464 16

投稿2017/08/26 16:08

編集2017/11/01 03:00
toritoritorina

総合スコア972

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

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

hososo

2017/08/27 03:15

とても分かりやすかったです。 そんな挙動があるとは…勉強不足でした。 本当にありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問