2017-10-05 3 views
1

私はMiller and RanumのPythonを使ったアルゴリズムとデータ構造に関する本を読んでいます。彼らは、次の例を使用します。Pythonの変数の再割り当て - オントロジクエリ - ニュートンメソッドを使用して

def squareroot(n): 
    root = n/2 
    for k in range(20): 
     root = (1/2)*(root + n/root) 

    return root 
私の質問は、変数「ルートは」のループ内に再割り当てされている

ので、その割り当ての右側の式の中で「ルート」の値が各反復でオペレータの変更。私はこれがどのように可能であるか分かりません。

関数呼び出しが行われると、forループ(2行目)の外側の 'root'変数は評価され、forループの式の 'root'変数によって参照されます式を代入演算子の左にあるfor-loopブロックの変数 'root'に再割り当てされる単一の値に評価することができます。次の反復の開始時に、 'root'はもはやn/2ではなく、forループの式が評価した値に関係なくです。この場合、変数 'root'はfloat値に再割り当てされ、元々は定義されていなかったものです。これは 'root'変数を使用する式です。

たとえば、関数呼び出しsquareroot(9)を使用すると、forループの式がその値に評価されるため、 'root'は最初の反復の後に3.25の値を保持します。 for-loopの変数 'root'がひとつのfloat値に再割り当てされると、もともと 'root'を定義した式は破棄されます。以来、 'root'は3.25として再定義されました。 for-loopの 'root'は、式を参照するのではなく、単一のfloat値を参照します。しかし、この例では、forループの 'root'変数には、各繰り返しの後に2つの意味があります。つまり、float値と式の両方です。私はそれがどのようにできるのか分かりません。

+0

あなたが理解しているように、変数「浮動小数点値」と「式である」との違いは何ですか? – mwchase

+0

変数は決して "式を指します"。その式を評価する*値*を参照します。たとえば、 'root = n/2'が実行されると、' root'は特定の数値を保持します。その数値はその時に 'n'が保持する値の半分になります。 'n'の値との継続的な関係はありません。 – jasonharper

答えて

1

短い答えは、Pythonはその式を抽象的な式として扱わないということです。それは実行される計算の具体的な一連として扱われます。ループを通過するたびに、現在の値rootでこれらの計算が実行され、結果がrootの値を更新するために使用されます。

import dis 
def squareroot(n): 
    root = n/2 
    for k in range(20): 
     root = 0.5 * (root + n/root) 
    return root 
dis.dis(squareroot) 

結果:

2   0 LOAD_FAST    0 (n) 
       3 LOAD_CONST    1 (2) 
       6 BINARY_DIVIDE  
       7 STORE_FAST    1 (root) 

    3   10 SETUP_LOOP    38 (to 51) 
      13 LOAD_GLOBAL    0 (range) 
      16 LOAD_CONST    2 (20) 
      19 CALL_FUNCTION   1 
      22 GET_ITER    
     >> 23 FOR_ITER    24 (to 50) 
      26 STORE_FAST    2 (k) 

    4   29 LOAD_CONST    3 (0.5) 
      32 LOAD_FAST    1 (root) 
      35 LOAD_FAST    0 (n) 
      38 LOAD_FAST    1 (root) 
      41 BINARY_DIVIDE  
      42 BINARY_ADD   
      43 BINARY_MULTIPLY  
      44 STORE_FAST    1 (root) 
      47 JUMP_ABSOLUTE   23 
     >> 50 POP_BLOCK   

    5  >> 51 LOAD_FAST    1 (root) 
      54 RETURN_VALUE   

興味深い部分は、割り当てに対応4から始まるブロックであり、そうのように、Pythonが実行する操作の実際の配列を見て役に立つかもしれませんあなたは尋ねた

  • 負荷スタックに以下:これは何が起こるかである[rootn、現在の内容のroot、現在の内容0.5、現在の内容]。最初の反復(n = 9)の間、スタックは[0.5、4.5、9.0、4.5]を保持します。
  • 最後の2番目の項目を最後の項目で除算し、結果をスタックに入れます。stack is now [0.5、4.5,2.0]
  • 最後の2つの項目をスタックに追加して代わりにスタック上の結果:スタックは今[0.5、6.5]
  • スタックの最後の2つのアイテムを乗算し、代わりに結果をスタックに入れます:スタックは今です[3.25]
  • 変数rootにスタック(3.25)を挿入します。

ご覧のとおり、式は、一連の手順を表しています。これらのステップの最後に、結果はrootに格納されます。次に、新しい値rootを使用してこれらのステップを再度実行することができます。

+0

これは素晴らしいことです。これをやってくれてありがとう - 私が与えたよりもはるかに良いイラストレーション。しかし、私はまだ理解しようとしています。最初の反復の後では 'root'の新しい値は3.25なので、「それは新しい値のrootでこれらのステップをやり直すことは可能です」というように、後続の反復ごとにその値を入れる式はありませんが、ルートの新しい値が3.25であり、(1/2)*(ルートの新しい値+(n /ルートの新しい値))ではないという私の主張。言い換えれば、式はもはや存在しません。「root」の値が再割り当てされました。 – efw

+0

@efw、関数的プログラミングのバックグラウンドから来ているようですが、Pythonは手続き的です。 Pythonプログラムは、スクリプトのように実行される一連のコマンドで構成されています。この場合、Pythonは(上記の)文に続き、kを1だけインクリメントしてから、まったく同じ文を繰り返します。だから次回は、私が記述したのとまったく同じですが、root = 4.5ではなくroot = 3.25から始まります。この式は、ルートに割り当てられて破棄されるオブジェクトではありません。それはルートの新しい値を計算するために従うべきスクリプトです。 –

+0

@マティアス・フリップありがとう。私は自分の間違いを理解していると思う。私は変数を解決しています - プログラミング言語そのものの代わりに、Pythonの変数を数学のレンズを通して見てきました。したがって、代入文の式は決して消えません。変数が参照する値に評価されますが、式は代入文の一部として残ります。変数は式を決して参照しませんが、式が評価する値を参照します。私が理解できるように、これをもっと大きな文脈に入れる時間をとってくれてありがとう。 – efw

関連する問題