2012-04-20 2 views
4

최근 Hacker Newsletter 호에는 Python의 데코레이터에 관한 this very useful article이 링크되었습니다. 나는 기사를 좋아하고 나는 대부분의 데코레이터 예제를 이해한다고 생각한다. 그러나, 비 장식의 메모이 제이션 예제에서, 나는 코드에 의해 매우 혼란 스러워요 :Python memoization 코드 스 니펫을 이해하려고 시도했습니다

def memoize(fn): 
    stored_results = {} 

    def memoized(*args): 
     try: 
      # try to get the cached result 
      return stored_results[args] 
     except KeyError: 
      # nothing was cached for those args. let's fix that. 
      result = stored_results[args] = fn(*args) 
      return result 

    return memoized 

나는이 기능이 추가 된 가져옵니다 지속 사전 stored_results을 만들 것입니다 방법에 대한 혼란 스러워요. 그것을 다시 읽은 후, 그것을 내 편집자에게 복사/붙여 넣기하고 그것을 가지고 노는 것과 도움을 얻기 위해 온라인으로 찾는 것, 나는 여전히 구문이 무엇인지 이해하지 못합니다. stored_results[args] = fn(*args).

(1)이 기사에서는 위의 코드가 함수를 반환하지만 이제는 새로운 인수로 실행하기 전에 사전을 먼저 검색 할 것이라고 제안합니다. 어떻게 될까요? stored_resultsmemoize에 국한되는 이유는 무엇입니까? memoized이 반송되면 왜 파괴되지 않습니까?

(2) *args으로 전달되는 인수를 설명하는 다른 질문이나 웹 리소스에 대한 링크도 도움이 될 것입니다. *args목록 인 경우 인수를 사용하면 왜 stored_results[args] 구문을 사용할 수 있습니까? 목록에서 사전 색인을 생성 할 때 일반적으로 해시 가능하지 않은 오류가 발생하는 이유는 무엇입니까?

의견을 보내 주셔서 감사합니다. 우리가 목록에 인덱스 사전을하려고 할 때 보통이 아닌 해쉬 오류 구문 stored_results[args]을 사용할 수 있습니다 왜 *args하면

답변

5

는 인수 목록입니다?

목록이 아니기 때문에 튜플입니다. 목록은 변경 가능하므로 의미있는 해시 함수를 정의 할 수 없습니다. 그러나 튜플은 변경 불가능한 데이터 구조입니다.

왜 stored_results는 memoize에만 국한되지 않습니까? memoized이 반송되면 왜 파괴되지 않습니까?

memoizememoized 주 같은 이름 컨텍스트 (폐쇄) 때문입니다. memoized에 대한 참조가 보유되어 있고이를 반환하고 전역 이름에 할당하기 때문에 클로저가 지속됩니다 (데코레이터 문의 효과). 클로저를 사용하면 캡처 한 모든 값도 유지됩니다.

+1

그래서'fn (* args)'는'args'의 원소로 된 튜플을'fn()'함수로 푸시합니다. 이것은'stored_results'가 * 전체 튜플 *에 의해 인덱스되는 엔트리를 가지고 있다는 것을 의미합니까? 링크의 예에서는 피보나치 함수를 사용합니다. 그래서 함수를 하나의 정수 인자, 즉'6'라고 부르면 사전은'{(6) : 8, ...} '과 같은 엔트리를 갖도록 확장 될 것입니까? 그렇다면 하나의 질문을 해결한다 : 그것은'args '로 가득 찬 전체 튜플이 하나의 암기 된 키로 사용된다고 가정한다. 여전히'stored_results'가 새로운 함수에 대한 여러 호출에서 지속되는 이유가 궁금합니다. – ely

+0

정의 된 내부 memoized 물건은 프록시에 의해서'stored_results'에 대해서만 알고있는 것처럼 보입니다. 파이썬은 내부적으로'memoized'의 정의가 그것을 가리 키기 때문에이 객체를 암시 적으로 유지합니까? – ely

+2

@EMS 예, memoized 함수는이 객체에 대한 참조를 가지고 있으므로 pythong은이를 가비지 수집하지 않습니다. "자유 변수"를 가진 이런 종류의 함수는 [closure] (http://en.wikipedia.org/wiki/Closure_ (computer_science))라고합니다. – tobyodavies

관련 문제