#Chapter05-03
#일급 함수(일급 객체)
#클로저 기초
#외부에서 호출한 함수의 변수값, 상태(레퍼런스) 복사 후 저장 -> 후에 접근(엑세스) 가능

#Closure 사용

#outer function을 호출해 놓고 inner function을 실행함으로써 outer function에 있는 자유변수를 활용해서 상태를 기억한다.
def closure_ex1():
    #Free variable (사용하려는 함수 바깥에서 사용된 것)
    #클로저 영역
    series = []
    def average(v):
        series.append(v)
        print('inner >>> {} / {}'.format(series, len(series)))
        return sum(series) / len(series)
    return average

avg_closure1 = closure_ex1()

print(avg_closure1(10))
print(avg_closure1(30))
print(avg_closure1(50))

print()
print()

#dir함수 : class나 instance 내부에서 사용할 수 있는 정보를 확인한다.
#__code__
#function inspection
print(dir(avg_closure1))
print()
print(dir(avg_closure1.__code__))
print()
print(avg_closure1.__code__.co_freevars)
print(avg_closure1.__closure__[0].cell_contents)
print()
print()

#잘못된 클로저 사용
def closure_ex2():
    #Free variable
    cnt = 0
    total = 0
    def average(v):
        cnt += 1
        total += v
        return total / cnt
    return average

avg_closure2 = closure_ex2()

#print(avg_closure2(10))

def closure_ex3():
    #Free variable
    cnt = 0
    total = 0
    def average(v):
        nonlocal cnt, total
        cnt += 1
        total += v
        return total / cnt
    return average

avg_closure3 = closure_ex3()
print(avg_closure3(15))
print(avg_closure3(35))
print(avg_closure3(40))
