2017-10-05 4 views
1

밀러와 라넘의 알고리즘과 데이터 구조에 대한 책은 Python을 사용하여 읽었습니다. 그들은 다음 예를 사용합니다파이썬의 변수 재 할당 - 온톨로지 쿼리 - Newton 메서드 사용

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

    return root 
내 질문은, 변수 '루트'는 대한 루프 내에 재 할당되고있다

그래서 할당의 오른쪽에있는 표현에서 '루트'의 값 반복 각각 운영자 변경. 어떻게 이것이 가능한지 잘 모르겠습니다.

함수 호출이 끝나면 for-loop 외부의 'root'변수 (2 행의 값)는 for 루프의 표현식에서 'root'변수에 의해 참조되는 값으로 평가됩니다 블록을 사용하여 표현식이 for 루프 블록에서 할당 연산자의 왼쪽에있는 변수 'root'에 다시 할당되는 단일 값으로 평가되도록합니다. 다음 반복의 시작에서 '루트'는 더 이상 n/2가 아니지만 for 루프의 표현식이 평가 한 값이 무엇이든간에. 이 경우, 'root'변수는 float 값으로 재 할당되었으므로 더 이상 원래 정의 된 것이 아니며 'root'변수를 사용하는 표현식입니다.

예를 들어 squareroot (9) 함수 호출을 사용하면 for 루프의 표현식이 해당 값으로 계산되기 때문에 'root'는 첫 번째 반복 이후 3.25의 값을 유지합니다. for-loop의 변수 'root'가 단일 부동 소수점 값으로 재 할당되면 원래 '루트'를 정의한 표현식이 삭제됩니다. 'root'는 이후 3.25로 재정의되었습니다. for-loop에서 'root'는 더 이상 표현식을 나타내지 않고 단일 부동 소수점 값을 나타냅니다. 그러나이 예제에서 for 루프의 'root'변수에는 각 반복 다음에 두 가지 의미가 있습니다. 이는 float 값과 expression 둘 다입니다. 나는 그것이 어떻게 될 수 있는지 이해하지 못한다.

+0

당신이 이해하고 있듯이, 변수 "float 값"과 "표현식"사이의 차이점은 무엇입니까? – mwchase

+0

변수는 절대로 "표현식을 참조하십시오". 그들은 그 표현을 평가하는 * value *를 참조합니다. 예를 들어,'root = n/2'가 실행될 때,'root'는'n'이 그때 가지고있는 값의 절반이되는 특정한 숫자 값을 가지고 있습니다; 'n' 값과의 지속적인 연결은 없습니다. – jasonharper

답변

1

짧은 대답은 파이썬이 표현식을 추상적 인 공식으로 취급하지 않는다는 것입니다. 수행 할 구체적인 일련의 계산으로 간주합니다. 루프를 통과 할 때마다 현재 값이 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로 시작하는 블록이다 너는 물었다.

  • 부하 스택으로 다음 :이 일어나는 것이다 [rootn의 현재 내용 root, 현재 내용 0.5, 현재 내용]. 첫 번째 반복 (n = 9) 중에 스택에 [0.5, 4.5, 9.0, 4.5]가 유지됩니다.
  • 스택의 마지막 항목을 마지막 항목으로 나눠서 결과를 스택에 넣으십시오. stack is now [0.5, 4.5, 2.0]
  • 스택의 마지막 두 항목을 추가하고 스택의 결과는 다음과 같습니다. 스택은 이제 [0.5, 6.5]
  • 스택의 마지막 두 항목을 곱하여 결과를 스택에 저장합니다. 스택은 이제 [3.25]
  • 의 마지막 항목을 변수 root에 스택 (3.25).

그래서 알 수 있듯이 표현식은 따라야 할 일련의 단계를 나타냅니다. 이러한 단계가 끝나면 결과는 root에 저장됩니다.그런 다음 새 값 root을 사용하여 해당 단계를 다시 수행 할 수 있습니다.

+0

이것은 아주 좋습니다. 이것을 해줘서 고맙다. - 내가주는 것보다 훨씬 더 훌륭한 일러스트레이션. 나는 아직도 이해하려고 노력하고있다. 첫 번째 반복 이후 'root'의 새 값은 3.25이므로 "루트의 새 값으로 해당 단계를 다시 수행 할 수 있습니다"라고 제안하면 이후 반복마다 해당 값을 넣을 표현식이 없습니다. 루트의 새로운 가치가 3.25이고 (1/2) * (루트의 새로운 값 + (루트의 새로운 값))이 아니라는 나의 주장. 즉, 표현식이 더 이상 존재하지 않습니다. 'root'의 값이 다시 할당되었습니다. – efw

+0

@efw, 함수 프로그래밍 배경에서 오는 것 같지만 파이썬은 더 절차 적입니다. 파이썬 프로그램은 스크립트처럼 실행될 일련의 명령으로 구성됩니다. 이 경우, Python은 (위에서 설명한) 문장을 따라 간 다음 k를 1 씩 증가시킨 다음 똑같은 문장을 반복합니다. 그래서 다음 번에 내가 설명했던 것과 똑같은 일을하지만 root = 4.5 대신 root = 3.25로 시작합니다. 표현식은 루트에 할당 된 다음 버려지는 객체가 아닙니다. 루트에 대한 새로운 값을 계산하기 위해 따라야 할 스크립트입니다. –

+0

@Mathias Fripp 감사합니다. 내 실수를 이해하고 있다고 생각합니다. 나는 변수를 해결하려고합니다. 프로그래밍 언어 그 자체 대신에 수학의 렌즈를 통해 파이썬 변수를 살펴 봤습니다. 따라서 대입 문의 표현식은 사라지지 않습니다. 변수가 참조하는 값으로 평가되지만 표현식은 대입 문의 부분으로 남아 있습니다. 변수는 표현식을 절대 참조하지 않고 표현식이 평가하는 값을 참조합니다. 더 큰 맥락에서 이것을 이해할 수 있도록 시간을내어 다시 한번 감사드립니다. – efw