「pythonは参照渡しではなく参照値の値渡し」云々についてここでは他の方に譲ります。
純粋にリストの場合との挙動の比較、また同じnumpyであっても計算式が異なると結果が異なる点について、説明します。
リストの場合、下記のように、関数呼び出し元と呼び出し先で、変数のid(識別値)が変わっておらず、同じオブジェクトにたいして要素の書き換えが行われていることがわかります。
lang
1def test1(x):
2 print("-関数内 計算前:",id(x))
3 x[0] = 9
4 print("-関数内 計算後:",id(x))
5 return x
6
7y=[0, 1, 2]
8print(y)
9print("関数 呼出前:",id(y))
10test1(y)
11print("関数 呼出後:",id(y))
12print(y)
実行結果
[0, 1, 2]
関数 呼出前: 2971572413192
-関数内 計算前: 2971572413192
-関数内 計算後: 2971572413192
関数 呼出後: 2971572413192
[9, 1, 2]
同様にnumpy配列でも、要素を置き換える場合は同じオブジェクトにたいしてデータ操作が行われます。
lang
1def test2(x):
2 print("-関数内 計算前:",id(x))
3 x[0] = 9
4 print("-関数内 計算後:",id(x))
5 return x
6
7y=np.arange(3)
8print(y)
9print("関数 呼出前:",id(y))
10test2(y)
11print("関数 呼出後:",id(y))
12print(y)
(実行結果はtest1と同様のため省略)
しかしながら、元コードのようにx=x-np.max(x)
という記述をすると、新しいnumpy配列が作成され、それに対して演算が行われるため、異なるオブジェクトの識別値が返ってくることになります。
下記のコードのようにx=x+1
で試してみましょう。
lang
1def test3(x):
2 print("-関数内 計算前:",id(x))
3 x = x + 1
4 print("-関数内 計算後:",id(x))
5 return x
6
7y=np.arange(3)
8print(y)
9print("関数 呼出前:",id(y))
10test3(y)
11print("関数 呼出後:",id(y))
12print(y)
実行結果
[0 1 2]
関数 呼出前: 2238140571440
-関数内 計算前: 2238140571440
-関数内 計算後: 2237889684544 <= 関数内ではidが変わっている!
関数 呼出後: 2238140571440 <= 関数を抜けた後は元のid
[0 1 2] <= yそのものは元の配列と変わらない(計算されたのは関数内で新たに作られたローカルオブジェクトx)
このように関数内でx=x+1とした時点で新しいオブジェクトが作成され、そのオブジェクトに対して演算が行われるため、呼び出し元のオブジェクトyは変わっていません。
ただし、「+=」という演算子を使うと、元のオブジェクトを書き換えることになります。
lang
1def test4(x):
2 print("-関数内 計算前:",id(x))
3 x += 1
4 print("-関数内 計算後:",id(x))
5 return x
6
7y=np.arange(3)
8print(y)
9print("関数 呼出前:",id(y))
10test4(y)
11print("関数 呼出後:",id(y))
12print(y)
実行結果
[0 1 2]
関数 呼出前: 1797431238704
-関数内 計算前: 1797431238704
-関数内 計算後: 1797431238704
関数 呼出後: 1797431238704 <= 関数内外ですべて同じid
[1 2 3] <= 配列の中身が書き換わっている
上記の挙動の違いは、「x=x+1」と「x+=1」の書き方によって、呼び出される足し算の計算挙動が異なっていることから生じているものと推測されます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/06/27 09:55
2020/06/27 12:33 編集
2020/06/27 12:47
2020/06/29 23:19
2020/06/30 04:16
2020/06/30 14:08 編集
2020/07/05 10:03
2020/07/06 20:14
2020/07/06 22:09
2020/07/06 22:47 編集
2020/07/08 12:30
2020/07/08 12:40
2020/07/08 12:54
2020/07/08 13:16
2020/07/08 13:49
2020/07/08 15:15
2020/07/08 19:43 編集
2020/07/09 12:03
2020/07/09 13:19