중첩 함수의 지역 변수
좋아요, 이것에 대해 참아주세요. 끔찍하게 복잡해 보일 것이라는 것을 압니다.하지만 무슨 일이 일어나고 있는지 이해하도록 도와주세요.
from functools import partial
class Cage(object):
def __init__(self, animal):
self.animal = animal
def gotimes(do_the_petting):
do_the_petting()
def get_petters():
for animal in ['cow', 'dog', 'cat']:
cage = Cage(animal)
def pet_function():
print "Mary pets the " + cage.animal + "."
yield (animal, partial(gotimes, pet_function))
funs = list(get_petters())
for name, f in funs:
print name + ":",
f()
제공 :
cow: Mary pets the cat.
dog: Mary pets the cat.
cat: Mary pets the cat.
그래서 기본적으로 왜 세 가지 다른 동물을 얻지 못합니까? cage
중첩 함수의 로컬 범위에 '패키징' 되지 않습니까? 그렇지 않은 경우 중첩 함수에 대한 호출은 지역 변수를 어떻게 조회합니까?
이런 종류의 문제가 발생한다는 것은 일반적으로 '잘못하는 것'을 의미한다는 것을 알고 있지만 어떤 일이 발생하는지 이해하고 싶습니다.
중첩 함수는 정의 될 때가 아니라 실행될 때 상위 범위에서 변수를 찾습니다.
함수 본문이 컴파일되고 '자유'변수 (할당에 의해 함수 자체에 정의되지 않음)가 확인 된 다음 코드가 각 셀을 참조하는 인덱스를 사용하여 함수에 클로저 셀로 바인딩됩니다. pet_function
따라서 하나의 자유 변수 ( cage
)가 있으며,이 변수 는 클로저 셀, 인덱스 0을 통해 참조됩니다. 클로저 자체 cage
는 get_petters
함수 의 지역 변수 를 가리 킵니다 .
실제로 함수를 호출 할 때, 그 폐쇄는 다음의 값을보고하는 데 사용되는 cage
주변 범위에서 함수를 호출 할 때 . 여기에 문제가 있습니다. 함수를 호출 할 때까지 get_petters
함수는 이미 결과 계산을 완료했습니다. cage
이 실행되는 동안 어떤 시점에서 로컬 변수가 각각 할당 된 'cow'
, 'dog'
그리고 'cat'
문자열을하지만 함수의 끝에서, cage
마지막 값을 포함한다 'cat'
. 따라서 동적으로 반환되는 각 함수를 호출하면 값이 'cat'
인쇄됩니다.
해결 방법은 클로저에 의존하지 않는 것입니다. 당신은 사용할 수있는 일부 기능을 대신 만드는 새로운 기능 범위를 A와 변수를, 또는 바인드 키워드 매개 변수에 대한 디폴트 값 .
다음을 사용하는 부분 함수 예제
functools.partial()
:from functools import partial def pet_function(cage=None): print "Mary pets the " + cage.animal + "." yield (animal, partial(gotimes, partial(pet_function, cage=cage)))
새 범위 예제 만들기 :
def scoped_cage(cage=None): def pet_function(): print "Mary pets the " + cage.animal + "." return pet_function yield (animal, partial(gotimes, scoped_cage(cage)))
변수를 키워드 매개 변수의 기본값으로 바인딩 :
def pet_function(cage=cage): print "Mary pets the " + cage.animal + "." yield (animal, partial(gotimes, pet_function))
scoped_cage
루프 에서 함수 를 정의 할 필요가 없습니다 . 컴파일은 루프의 각 반복이 아니라 한 번만 발생합니다.
내 이해는 산출 된 pet_function이 실제로 호출 될 때 부모 함수 네임 스페이스에서 케이지가 이전이 아니라 호출된다는 것입니다.
그래서 당신이 할 때
funs = list(get_petters())
마지막으로 생성 된 케이지를 찾는 3 개의 함수를 생성합니다.
마지막 루프를 다음으로 바꾸면 :
for name, f in get_petters():
print name + ":",
f()
당신은 실제로 얻을 것입니다 :
cow: Mary pets the cow.
dog: Mary pets the dog.
cat: Mary pets the cat.
이것은 다음에서 비롯됩니다.
for i in range(2):
pass
print i is 1
after iterating the value of i
is lazily stored as its final value.
As a generator the function would work (i.e. printing each value in turn), but when transforming to a list it runs over the generator, hence all calls to cage
(cage.animal
) return cats.
참고URL : https://stackoverflow.com/questions/12423614/local-variables-in-nested-functions
'programing' 카테고리의 다른 글
Maven : 라이브러리에서 추가 한 종속성을 재정의하는 방법 (0) | 2020.08.18 |
---|---|
: nth-child () 또는 : nth-of-type ()을 임의의 선택기와 결합 할 수 있습니까? (0) | 2020.08.18 |
WPF TextBlock 요소와 Label 컨트롤의 차이점은 무엇입니까? (0) | 2020.08.18 |
PHP에서 리퍼러 결정 (0) | 2020.08.18 |
JavaScript를 사용하여 스크롤 막대 너비 가져 오기 (0) | 2020.08.17 |