
def func_v1(a):
print(a)
print(b)
func_v1(5)
# 오류
b = 10
def func_v2(a):
print(a)
print(b)
func_v2(5)
# 5 10
b = 10
def func_v3(a):
print(a)
print(b)
b = 5
func_v3(5)
# 5
# 오류
클로저:
반환되는 내부 함수에 대해서 선언 된 연결을 가지고 참조하는 방식
반환 당시 함수 유효범위를 벗어난 변수 또는 메소드에 직접 접근이 가능하다.
class Averager():
def __init__(self):
self._series = []
def __call__(self,v):
self._series.append(v)
print('class >>> {} / {}'.format(self._series, len(self._series)))
return sum(self._series) / len(self._series)
avg_cls = Averager() # 객체 생성
print(avg_cls(10))
# class >>> [10] / 1
# 10.0
print(avg_cls(20))
# class >>> [10, 20] / 2
# 15.0
print(avg_cls(30))
# class >>> [10, 20, 30] / 3
# 20.0
def closure_avg1():
# Free variable
series = []
# 클로저 영역
def averager(v):
# series = [] # check
series.append(v)
print('def >>> {} / {}'.format(series, len(series)))
return sum(series) / len(series)
return averager # 함수를 호출만 한다.
avg_closure1 = closure_avg1() # 함수 담기
print(avg_closure1(15))
# def >>> [15] / 1
# 15.0
print(avg_closure1(35))
# def >>> [15, 35] / 2
# 25.0
print(avg_closure1(40))
# def >>> [15, 35, 40] / 3
# 30.0
def closure_avg2():
# Free variable
cnt = 0
total = 0
# 클로저 영역
def averager(v):
cnt += 1
total += v
print('def2 >>> {} / {}'.format(total, cnt))
return total / cnt
return averager
avg_closure2 = closure_avg2()
print(avg_closure2(15)) # 오류
print(avg_closure2(35)) # 오류
print(avg_closure2(40)) # 오류
위 코드에서 보면 변수 cnt와 total이 averager함수에서 선언이 되어있지 않아서 오류가 난다.
Free variable을 참조하지 않는다.
오류: UnboundLocalError: local variable 'cnt' referenced before assignment
해결방법은?
nonlocal cnt, total 을 선언해서 변수를 참조하게 한다. ```python
def closure_avg2():
# Free variable
cnt = 0
total = 0
# 클로저 영역
def averager(v):
nonlocal cnt, total
cnt += 1
total += v
print('def2 >>> {} / {}'.format(total, cnt))
return total / cnt
return averager
avg_closure2 = closure_avg2()
print(avg_closure2(15))
def2 >>> 15 / 1
15.0
print(avg_closure2(35))
def2 >>> 50 / 2
25.0
print(avg_closure2(40))
def2 >>> 90 / 3
30.0