2017-04-08 9 views
2

함수를 작성하십시오. make_monitored은 입력으로 함수 f를 취하고 하나는 그 입력을 취합니다. make_monitors가 반환하는 결과는 내부 카운터를 유지 관리하여 호출 된 횟수를 추적하는 세 번째 함수, 예를 들어 mf입니다.다른 함수를 모니터하고 계산하는 함수 Python

mf에 대한 입력이 "how-many-calls?"와 같은 특수 문자열 인 경우 mf는 카운터의 값을 반환합니다.

입력이 특수 문자열 "reset-count"인 경우 mf는 카운터를 0으로 재설정합니다. 다른 입력의 경우 mf는 해당 입력에서 f를 호출 한 결과를 반환하고 은 카운터를 증가시킵니다. 내가 내부 카운터로 만들 수있는 하나 개의 요소 목록을 만들고 싶어 여기

def make_monitored(f): 
    a=[0] 
    def mf(x): 
     if x=="how-many-calls?": 
      return a[0] 
     elif x=="reset-count": 
      a=[0] 
     else: 
      a[0]+=1 
      return f(x) 
    return mf 


def double(x): #NOT TO BE CHANGED , provided by question 
    return 2 * x 

d = make_monitored(double) #NOT TO BE CHANGED, provided by question 

내가 이해 해달라고 것입니다. 나는 그들이 make_monitors가 부모 함수이고 정의 된 것을 정의하지 않은 이유를 알지 못한다.

이것은 비슷한 방법을 사용했지만 성공한 이전에 완료 한 또 다른 질문입니다.

누적 기는 하나의 숫자 인수 을 반복적으로 호출하여 해당 인수를 합계에 누적하는 함수입니다. 호출 할 때마다 현재 누적 합계 을 반환합니다. accumulators를 생성하는 make_accumulator 함수를 작성하십시오. 각 함수는 독립적 인 합계를 유지합니다.

def make_accumulator(): 
    lst=[0] 
    def add(x): 
     lst[0]+=x 
     return lst[0]  
    return add 
A=make_accumulator() 

샘플 실행 :

A = make_accumulator()

A (10) 출력 : 10

A (10) 출력 : 20

I 이유 얻을 해달라고 lst [0]은 여기에 정의되어 있습니다. 유일하게 가능한 이유는 make_accumulator 매개 변수없이에 걸리지 만 할당 a = [0]mf에 로컬 새로운 a을 생성 1. ​​

답변

1

에 make_monitored 걸릴 않는다는 것입니다. 즉, a에 대한 다른 모든 참조는 mf에 있어야하며 부모의 주소 대신 로컬 a이어야합니다.

그래서 a에 자신을 할당 피하고 대신 그것을 돌연변이 :

a[0] = 0 

은 BTW, 파이썬 3는 이런 종류의 물건에 대한 편리 새 키워드 nonlocal을 제공합니다. 그것은 global 키워드와 유사하게 작동합니다. 그리고 여기에 사용하여 카운터 또는 누적 기의 간단한 int를 사용할 수 있습니다.

+0

덕분에, 그것을 파이썬 3.6을 사용하여 – Silver

1

closure은 자체 환경 내에있는 기능을 정의합니다. 이렇게하면 우리 함수가 여분의 상태를 추적 할 수 있습니다.

내부 함수를 정의 할 때 변수 a는 내용 [0]이있는 목록에 할당됩니다.

당신이 할 때 :

elif x=="reset-count": a=[0] 당신은 우리의 내부 함수에 로컬 브랜드의 새로운 목록에 할당된다 그것은 더 이상 외부에 정의 된 'a'에 대해 알지 못합니다.

nonlocal 키워드를 사용하여 클로저의 상태를 추적합니다. E.G :

def count_calls(func): 
    calls_so_far = 0 
    def inner(x): 
     nonlocal calls_so_far # this allows us to keep track of state 
     if x == 'how-many-calls' 
      return calls_so_far 
     if x == 'reset-count': 
      calls_so_far = 0 
     else: 
      calls_so_far += 1 
      return func(x) 
    return inner 


@count_calls # this is a DECORATOR 
def double(x): 
    return 2*x 

# This decorator is equivalent to the following: 
""" 
def double(x): 
    return 2*x 
double = count_calls(double) 
""" 

파이썬 2에서는 nonlocal 키워드를 사용할 수 없습니다. 대신, 어떤 종류의 변경 가능한 컨테이너를 변경해야합니다. 목록을 사용하고 첫 번째 요소를 변경하는 것은 일반적인 접근 방식이며 예제 코드에서 볼 수 있습니다. 직관적이지 않고 실수하기 쉽기 때문에 비 로컬 접근법은 더 관용적 인 파이썬으로 간주됩니다. PYTHON 3.6 (! 스스로를 실행 해보십시오)에 대한

범위의 예 :

x = 'GLOBAL' 
def outer(): 
    print('running outer()') 
    x = 'OUTER' 
    print(f'\tx = {x}') 
    def inner(): 
     print('\t\trunning inner()') 
     x = 'INNER' 
    def inner_nonlocal(): 
     nonlocal x 
     print('\t\trunning inner_nonlocal()') 
     x = 'INNER_NONLOCAL' 
    inner() 
    print(f'\tx = {x}') 
    inner_nonlocal() 
    print(f'\tx = {x}') 

print('before running outer()') 
print(f'x = {x}') 
outer() 
print('after running outer()') 
print(f'x = {x}') 
+0

메신저를 해결하기 위해 관리. 따라서 유일한 방법은 목록과 같은 변경 가능한 데이터 구조를 사용하는 것입니다. – Silver

+0

아니요. 로컬이 아니어도 사용할 수 있습니다. 범위 규칙의 교훈적인 예와 도움이 될 수있는 지역 외 사용을 편집했습니다. –

+0

도움을 주셔서 감사합니다. 그것은 매우 유용합니다. 시간과 도움에 감사드립니다! – Silver