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

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

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

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

Q&A

解決済

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

faker
faker

総合スコア50

Python 3.x

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

3回答

0グッド

0クリップ

180閲覧

投稿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

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

PondVillege

2023/01/17 09:05

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

2023/01/17 17:07

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

回答3

1

自己解決

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

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

投稿2023/01/17 17:12

編集2023/01/17 17:14
faker

総合スコア50

ps_aux_grep👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

1

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

変更は可能です。

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

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

総合スコア10513

bsdfan👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

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

総合スコア36264

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

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

ただいまの回答率
86.02%

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

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

質問する

関連した質問

同じタグがついた質問を見る

Python 3.x

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