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

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

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

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

Q&A

解決済

3回答

745閲覧

Pythonのfor文でリスト内の要素が変更できているのですが、なぜですか。

faker

総合スコア51

Python 3.x

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

0グッド

0クリップ

投稿2023/01/17 08:47

Pythonはfor文でループ元の変数は変更できないと思っていました。しかし、この場合はループ元変数のdictsが変更できています。これはなぜですか?

該当のソースコード

dict ... 辞書型の変数
dicts ... 辞書型の変数をリストで持つ変数

Python

1>>> dicts = [{"a": 1, "b": 10}, {"a": 1, "b": 10}] 2>>> for dict in dicts: 3... dict.update({"c": 1000}) 4... 5>>> dicts 6[{'a': 1, 'b': 10, 'c': 1000}, {'a': 1, 'b': 10, 'c': 1000}]

補足情報(FW/ツールのバージョンなど)

Python 3.9.13

Pythonのfor文でループ元変数の値が変更できないと思ったサイト
https://ja.stackoverflow.com/questions/31916/%E3%83%AA%E3%82%B9%E3%83%88%E3%81%AB%E5%90%AB%E3%81%BE%E3%82%8C%E3%82%8B%E5%A4%89%E6%95%B0%E3%81%AE%E5%80%A4%E3%82%92for%E6%96%87%E3%81%A7%E5%A4%89%E6%9B%B4%E3%81%97%E3%81%9F%E3%81%84

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

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

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

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

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

PondVillege

2023/01/17 09:05

mutableとimmutableについて調べて,分からないことがあれば質問に追記してください.
faker

2023/01/17 17:07

理解できました!mutableだから変更できたんですね。
guest

回答3

0

自己解決

リスト内の値が変更できた理由は質問に示したコードのdict型変数のdictがmutableだったから、でした。
参考にしていたページでは、ループ変数がint型でimmutableだから変更ができない、と理解しました。

mutable, immutableはこのサイトがとても参考になりました。

投稿2023/01/17 17:12

編集2023/01/17 17:14
faker

総合スコア51

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

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

0

「ループ元の変数は変更できないと思って」いたのはなぜですか?

変更は可能です。

ただし、以下のようにしても、元のリストは変更できません。

python

1a = [1, 2, 3] 2for i in a: 3 i = i * 2 4print(a)

これもだめです。

python

1a = [{'val_a': 1, 'val_b': 2}, {'val_a': 10, 'val_b': 20}] 2for i in a: 3 i = {'val_a': 100, 'val_b': 200} 4print(a)

これはリストの要素がimutableなものでもmutableなものでも同様です。

だだし、ループ変数(この場合はi)は、リストのメンバーそのものに束縛されているので、そのものを変更するような操作をすれば、リストの要素を変更することができます。

python

1a = [{'val_a': 1, 'val_b': 2}, {'val_a': 10, 'val_b': 20}] 2for i in a: 3 i['val_b'] = 1000 4print(a)

質問のupdateメソッドも同様です。
これは、このときリストを構成しているのがimutableなデータである辞書であり、その辞書そのものを変更しているからです。
リストの要素が文字列や整数のようなimutableなデータの場合、そのものを変更する方法が無いので、ループ変数を使ってリストの内容を変更することはできません。

投稿2023/01/17 09:43

TakaiY

総合スコア12765

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

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

0

まず、ちょっと異なる動きについての説明ですが出力引数のある関数 (参照渡し) はどのように書きますか?

(略)代入はオブジェクトへの参照を作るだけなので、(略)

という記載に注目してください。
これはa=123といった代入はa123というオブジェクトを指す、という意味になります。

そのうえで、以下においてループ中のeは、リストの中の{'key':123}を指しています。
そしてそれに対してe.update({'key':456})という操作を行っているため、指している中身が変わります。

lst = [{'key':123}] for e in lst: print(e, id(e)) # {'key': 123} 2435079527744 e.update({'key':456}) print(e, id(e)) # {'key': 456} 2435079527744 print(lst) # [{'key': 456}]

ちなみに上記コードにおいてid(~)というのは、その指しているモノを識別するID値を返す関数です。
そしてその値が同じ、すなわちeが操作の前後で同じモノを指していることが分かります。

次に、以下のコードにおいてループ中のeは、先の例と同じくリストの中の{'key':123}を指しています。
しかしe = {'key':456}という代入によって{'key':456}という別のオブジェクトを指すようになります。
これはそのあとのID値が異なっていることでも確認できます。
eは別のオブジェクトを指すようになっただけで元のリストは何も変わりません

Python

1lst = [{'key':123}] 2for e in lst: 3 print(e, id(e)) # {'key': 123} 2435076163328 4 5 print(e, id(e)) # {'key': 456} 2435076163584 6 7print(lst) # [{'key': 123}]

投稿2023/01/17 09:31

編集2023/01/17 09:33
can110

総合スコア38266

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問