>  기사  >  백엔드 개발  >  Python 클로저의 변수 참조 분석

Python 클로저의 변수 참조 분석

巴扎黑
巴扎黑원래의
2016-12-08 10:57:021293검색

제목이 굉장히 호랑이 같아 보이지만 사실 감히 분석이라고 할 수는 없습니다. 이 분야에는 아직 부족한 부분이 있습니다. 예전에는 괜찮았을지 모르지만 지금은 언어를 공부할 시간과 에너지가 부족합니다. 설명에 문제가 있으면 Banzhu에 오셔도 좋습니다.

이번에는 문제에 대해 직접 이야기해 보겠습니다. 오늘은 @neiddy(javaeye)가 클로저 문제에 대해 이야기해 주었습니다. 그 몇 가지 예를 보니 흥미롭고 이해하고 싶습니다.

두 가지 코드 보기:

>>> def foo():
       a = 1
       def bar():
              a = a +1
              return a
       return bar()
 
>>> foo()
Traceback (most recent call last):
  File "<pyshell#73>", line 1, in <module>
    foo()
  File "<pyshell#72>", line 6, in foo
    return bar()
  File "<pyshell#72>", line 4, in bar
    a = a +1
UnboundLocalError: local variable &#39;a&#39; referenced before assignment
>>> def foo():
       a = [1]
       def bar():
              a[0] = a[0] + 1
              return a[0]
       return bar()
 
>>> foo()2

클로저를 통해 함수형 프로그래밍을 경험하는 것은 여전히 ​​좋은 느낌입니다. 원본 텍스트 아래에는 괄호가 없습니다. 그렇지 않으면 반환 함수 자체가 의미가 없습니다. 이 마법같은 현상에 대해 이야기해보자. 기사에서는 컨테이너로 바꾸면 괜찮을 것이라고만 나와 있다. 왜일까?

메모리 관리와 메모리 할당에 대해 구글링을 해보았으나 방법이 없어 소스코드를 찾아보았습니다. 본 적도 없고 직접 읽기에는 너무 비효율적이지만 다행히 누군가가 정리해서 "Yuhen Q.yuhen"의 "심층 Python 프로그래밍"을 추천해 주었습니다.

직접 폐쇄 부분의 코드 분석은 클로저 섹션에서 언급했지만, 이 이상한 문제에 대해 구체적으로 이야기할 메커니즘은 없습니다.

책을 다시 읽고 책에 있는 '매개변수'와 '클로저' 부분을 참고하여 그의 설명과 첨부된 소스코드를 바탕으로 제가 이해한 내용을 이야기해보겠습니다.

Yu Cheng은 장 마지막에 "CPython의 클로저 구현 원리는 복잡하지 않습니다. 직설적으로 말하면 참조된 외부 객체를 매번 다시 생성되는 내부 함수 객체에 연결하는 것입니다( func_closure ). "

이 문장은 이전 문장을 요약한 것이며, 중요한 정보도 포함되어 있습니다. 즉, 내부 함수에 해당하는 객체는 실제로 외부 변수를 참조하여 외부 함수에 있는 변수에 액세스합니다. 객체의 스택에서 액세스되며 C 언어 코드의 값으로 전달됩니다.

예를 들어 첫 번째 코드의 a는 실제로 1을 참조하고 자체 co_nlocals는 1입니다. 즉, 지역 변수는 등호 앞의 a입니다. 이 질문을 이해하는 데 도움이 됩니다.) 지역 변수 a이므로 a = a +1은 UnboundLocalError를 발생시켜야 합니다.

두 번째 질문은 같은 상황이더라도 값으로 전달하더라도 배열의 각 위치가 가리키는 특정 지점은 변하지 않고 지정된 위치의 값은 그대로 유지됩니다. 수정이 가능하므로 컨테이너 객체라면 가능합니다.

명확하게 설명할 수 없다는 게 늘 제 자신에게 싫습니다. 사실 C 언어를 처음 배울 때 자주 했던 포인터 게임입니다. 설명이 끔찍합니다. 위험하다고 지적할 수 있기를 바랍니다. 다음 단계는 매우 간단합니다. 즉, 이 값만 출력하고 로컬 변수를 설정하지 않으면 실행될 수 있습니다.

>>> def foo():
       a = 1
       def bar():
              return a
       return bar()
 
>>> foo()
1

일이 예상대로 일어났습니다. 좀 더 꼼꼼히 경험해 보시려면 Yuhen이 분석한 코드를 잘 살펴보세요. 역학을 이해하는 것은 큰 도움이 됩니다. Python은 점점 더 흥미로워지고 있습니다. Python 아이디어로 코드를 작성하면 많은 이점이 있습니다.

그런데 그런데

>>> flist = []
>>> for i in range(3):
       def foo(x): print x + i
       flist.append(foo)
 
>>> for f in flist:
       f(2)
 
4
4
4

이 코드는 i가 파괴되지 않아서 발생한다고 기사에 나와 있는데 오늘 메모리 할당 검색을 하다가 이런 내용을 봤습니다. 프로그래밍할 때, 함수형 프로그래밍은 간결하고 명확하지만, 성능을 향상시키고 카운터를 절약하기 위해 목록 이해를 사용해야 합니다.

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.