

できる限り同条件で比較できるコードにしたつもりなのですが、何度やってもリストはインプレースで書き換えられてしまいます。なぜなのでしょうか？「リストの代わりにタプルを使うべき」以外の回答だとありがたいです。

また、初の質問投稿であるため、無作法な点もあるかと思うので、その点の指摘があるとなお助かります。よろしくお願いします。

[code]

    >>> lst,a = [0],0
    >>> def test1(lst):
        try:
            _ = lst
            _[0] = 1
        except:
            pass
        return _
    >>> def test2(x):
        try:
            b = a
            b = 1
        except:
            pass
        return b
    >>> test1(lst)
    [1]
    >>> lst
    [1]　#ここが0のままであってほしい
    >>> test2(a)
    1
    >>> a
    0
    
[/code]


CC BY-SA 4.0
2020-10-12T09:34:02.590
71132
2020-11-30T12:51:08.683
2020-10-12T11:47:16.827
3060
42290
question
python python3
Python3.6.4 の関数内の変数に関して、インプレースで変更される場合とそうでない場合の違いは？


質問のコードでは`id(test1(lst))`と`id(lst)`は同一であり同じものを指しています。  
質問のコードを下記のようにすると良いでしょう。

[code]

    def test1(lst):
        try:
            _ = lst.copy()
            _[0] = 1
        except:
            pass
        return _
    
[/code]


CC BY-SA 4.0
2020-11-11T05:58:15.287
71862
2020-11-11T05:58:15.287
39819
71132
answer


Python のオフィシャルの FAQ に説明があるので、まずはそれを読むとよいでしょう：

  * [なぜ list 'y' を変更すると list 'x' も変更されるのですか?](https://docs.python.org/ja/3/faq/programming.html#why-did-changing-list-y-also-change-list-x)

簡単に補足すると、リストのようなオブジェクトを作ると、要素の中身を保存するような実体がひとつ作られ、オブジェクトそのものに対して関数の引数渡しや変数代入をすると、中身の実体が新たに作られるということはなく、それを指す参照が渡されるということです。

というわけで、関数の引数にリストを渡すときに、渡した先の関数がもとのリストを改変するのを防ぐためには、引数に `lst` を渡す代わりに、 `lst[:]`
や `lst.copy()` を渡して、新しいリストを作って渡せばよいということになります。もしくは、 `tuple(lst)`
のように中身を改変できない配列であるタプルを作って渡してもよいでしょう（この場合、タプルを受け取った変数がその中身を変えようとするとエラーになります）。


CC BY-SA 4.0
2020-11-30T12:51:08.683
72297
2020-11-30T12:51:08.683
40595
71132
answer