• ベストアンサー

Pythonのファンシーインデックスを用いた代入

Python初心者です。 Pythonのファンシーインデックスを用いた代入についての質問です。 import numpy as np x = np.zeros(10, dtype = int) x[0] = 1 i = np.arange(10) i_dly = np.append(0, i)[:len(i)] x[i] = x[i_dly] print(x) というコードで、print結果が [1 1 1 1 1 1 1 1 1 1] となるのを期待したのですが、結果は [1 1 0 0 0 0 0 0 0 0] でした。 [1 1 1 1 1 1 1 1 1 1]とならない理由を教えていただけないでしょうか。 よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

> デフォルトでは、とのことですが、設定次第ではswappableではない状態に変更する手段があるということでしょうか。swapping可、swappableをキーワードにして浅く調べてみたのですが、swapする方法が出てくるだけで有効な情報が見つかりませんでした。 基本的には「無い」。 問題は、Numpyのファンシーインデックスに関する操作は、あたかも「全ての値を並列で代入操作してる」ように見せかけているトコにある。 つまり、理論的な話をすると、Pythonのこのテの「見せかけ」は逐次処理を避けてるように見せる、と言うトコによる。 逐次処理: https://kotobank.jp/word/%E9%80%90%E6%AC%A1%E5%87%A6%E7%90%86-5728 Pythonはその設計の初期の段階で、関数型言語に影響を受けている・・・。 関数型プログラミング: https://ja.wikipedia.org/wiki/%E9%96%A2%E6%95%B0%E5%9E%8B%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0 と言うより、ホント初期の段階で関数型言語ユーザーが群がった為(笑)、それらユーザーの要求に「応えた」ってのがあったんだ。 従って、「何かを順番に処理していく」より「処理の順番は大した問題じゃない」と見せかけるトリックを採用する事にした。 swappingがそうした例の一つで、 a, b = b, a が簡単に成り立つようにした、ってのは「aが処理された後bが処理される」のではなく、「aとbが同時に処理される」方が、関数型言語ユーザーには自然に思える、と言うような事を引きずってるから、なんだ。 と言う事は、単純に、「関数型プログラミング的な」ファンシーインデックスを用いた代入を止めて、逐次処理に頼ればいい、って事だ。いわゆる「反復構文」は逐次処理と密接に関係する。 import numpy as np x = np.zeros(10, dtype = int) x[0] = 1 i = np.arange(10) i_dly = np.append(0, i)[:len(i)] for m, n in zip(i, i_dly): x[m] = x[n] print(x) そうすれば、貴方が望むように、 [1 1 1 1 1 1 1 1 1 1] が得られるだろう。 繰り返すが、関数型プログラミングは「コードを短く書いて」「あたかも処理順序が存在せずに全て同時に物事が成される」ように見せかける方法論で、ザーッと見たカンジだと「ファンシーインデックス」ってのはそれをサポートする為の方法論だ。 従って、ファンシーインデックスによる代入は「逐次処理」的な効果を持たない。また、numpy自体がそもそも「数学的処理」を念頭に置いたライブラリなんで、「関数型プログラミング」的にある程度動作するのは、望まれた効果だろう。 一方、逐次処理に頼りたいのなら、ホンマ「順番に」処理していった方が良い、って事だ。無理してファンシーインデックス操作をすると、貴方観点だと「予想外の動作になる」って事だな。

4Hswu8RwXU7Za4D
質問者

お礼

詳細で簡潔な回答ありがとうございました。 非常に助かりました。

Powered by GRATICA
4Hswu8RwXU7Za4D
質問者

補足

詳細で簡潔な回答ありがとうございました。 非常に助かりました。

すると、全ての回答が全文表示されます。

その他の回答 (1)

回答No.1

✗Pythonのファンシーインデックス ○Numpyのファンシーインデックス 原則、これはPythonに付いての質問ではなく、Numpyに付いての質問となる。 結果、本当なら、ここに投げるべき質問じゃなくってNumpyの公式に投げるべき質問だろう。 Numpy コミュニティ: https://numpy.org/ja/community/ 外部ライブラリは多岐に渡ってる為、「Python」と言うカテゴリでは追っつけないのが現状だ。 「言語実装に対する質問」と「外部ライブラリに付いて」は分けなければならない、ってのが実情だ。 そして、外部ライブラリを使う限り、「どこが質問を投げる場所なのか」は把握しておかないとならない。メーリングリスト、とかな。 プログラムの定義によると、 i = array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) idly = array([0, 0, 1, 2, 3, 4, 5, 6, 7, 8]) になってる。 従って、 x[i] = x[i_dly] と言う代入は index x[i] i_dly x[i_dly] 0 1 0 1 1 0 0 1 2 0 1 0 3 0 2 0 4 0 3 0 5 0 4 0 6 0 5 0 7 0 6 0 8 0 7 0 9 0 8 0 になる。 もうちょっと細かく見ると、 x[0] = x[0] => x[0] = 1 x[1] = x[0] => x[1] = 1 x[2] = x[1] => x[2] = 0 x[3] = x[2] => x[3] = 0 x[4] = x[3] => x[4] = 0 x[5] = x[4] => x[5] = 0 x[6] = x[5] => x[6] = 0 x[7] = x[6] => x[7] = 0 x[8] = x[7] => x[8] = 0 x[9] = x[8] => x[9] = 0 と言う事だ。何も不思議なトコはない。 恐らく貴方が混乱してる原因は、Pythonの代入が「swappable」だと言う事を押さえてないトコから来てると思われる。 >>> a, b = 1, 2 >>> a, b = b, a >>> a 2 >>> b 1 Pythonでの変数はswap動作がデフォルト動作になっていて、「代入に使われる値」は「代入が行われる前」の値が使われる。 貴方の混乱は、「変数が代入済みなのに何で代入以前の値が使われてるの?」と言う辺りだろうが、Pythonの変数がデフォルトでは「swapping可」になってるトコをキチンと理解していれば、この動作は納得するだろう。例えばx[2] = x[1]で使われるx[1]は代入後である1ではなく、代入以前の(退避された)0である、と言った具合に。

4Hswu8RwXU7Za4D
質問者

補足

詳細な回答ありがとうございます。 > Numpyの公式に投げるべき質問だろう。 失礼しました。失礼を重ねてしまいますが、追加で質問させていただけないでしょうか。 > Pythonでの変数はswap動作がデフォルト動作になっていて、 > Pythonの変数がデフォルトでは「swapping可」になってる デフォルトでは、とのことですが、設定次第ではswappableではない状態に変更する手段があるということでしょうか。swapping可、swappableをキーワードにして浅く調べてみたのですが、swapする方法が出てくるだけで有効な情報が見つかりませんでした。

すると、全ての回答が全文表示されます。

関連するQ&A