<jupyter_start><jupyter_text>Inflearn 파이썬 중급 - 파이썬 일급함수 - 클로저 (2-1, 2-2, 3-1, 3-2)- toc: false- badges: false- comments: true- author: <NAME>- categories: [ ___  A. ENGINEERING __________ > PYTHON 인프런 강의] - - -- - - 파이썬 변수 범위(Scope)<jupyter_code>## Ex1
def func_v1(a):
	print(a)
	print(b)

func_v1(10)  #NameError: name 'b' is not defined


## Ex2
b = 20

def func_v2(a):
	print(a)
	print(b)

func_v2(10)

## Ex3

c = 30

def func_v3(a):
	print(a)
	print(b)
	c = 40

print(">> c =", c)
func_v3(10)
print(">>> c =", c)<jupyter_output>>> c = 30
10
20
>>> c = 30<jupyter_text>- - - Global 선언<jupyter_code>## Ex4
c = 30

def func_v4(a):
	global c
	print(a)
	print(b)
	c = 40

print("- - -")
print(">> c =", c)
func_v4(10)
print(">>> c =", c)<jupyter_output>- - -
>> c = 30
10
20
>>> c = 40<jupyter_text>- - - 클로저 사용 이유- 해당 시점의 상태를 save하고 있다.- 서버 프로그래밍 -> 동시성(concurrency) 제어 -> 메모리 공간에 여러 자원이 접근 -> 교착상태(Dead lock)- 메모리를 공유하지 않고 메시지 전달로 처리하기 위한 -> Erlang- 클로저는 공유하되 변경되지 않는(Immutable, Read only) 적극적으로 사용 -> 함수형 프로그래밍- 클로저는 불변자료구조 및 atom, STM -> 멀티스레드(Coroutine) 프로그래밍에 강점<jupyter_code>a = 100

print(a + 100)
print(a + 1000)

# 결과 누적(함수 사용)
print(sum(range(1,51)))
print(sum(range(51,101)))<jupyter_output>1275
3775<jupyter_text>- - - Class -> Closure 구현<jupyter_code># 클래스 이용
class Averager():
	def __init__(self):
		self._series = []
	
	def __call__(self, v):
		self._series.append(v)
		print('inner >> {} / {}'.format(self._series, len(self._series)))
		return sum(self._series) / len(self._series)

# 인스턴스 생성
averager_cls = Averager()

# 누적
print(averager_cls(10))
print(averager_cls(30))
print(averager_cls(50))
print(averager_cls(10))<jupyter_output>inner >> [10] / 1
10.0
inner >> [10, 30] / 2
20.0
inner >> [10, 30, 50] / 3
30.0
inner >> [10, 30, 50, 10] / 4
25.0<jupyter_text>- - - 클로저 사용 예제<jupyter_code>def closure_ex1():
	# 클로저 영역
	series = [] # Free variable (자유변수)
	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))


# 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)<jupyter_output>['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'co_argcount', 'co_cellvars', 'co_code', 'co_consts', 'co_filename', 'co_firstlineno', 'co_flags', 'co_freevars', 'co_kwonlyargcount', 'co_lnotab', 'co_name', 'co_names', 'co_nlocals', 'co_stacksize', 'co_varnames']

('[...]<jupyter_text>- - - 잘못된 클로저 사용<jupyter_code># 잘못된 사용
def closure_ex2():
	cnt = 0
	total = 0
	def averager(v):
		cnt += 1
		total += v
		return total / cnt
	return averager

avg_closure2 = closure_ex2()
print(avg_closure2(10))

# 개선
def closure_ex3():
	cnt = 0
	total = 0
	def averager(v):
		nonlocal cnt, total
		cnt += 1
		total += v
		return total / cnt
	return averager

avg_closure3 = closure_ex3()
print(avg_closure3(15))
print(avg_closure3(35))
print(avg_closure3(40))<jupyter_output>15.0
25.0
30.0
{'fraction_non_alphanumeric': 0.18482794577685088, 'fraction_numerical': 0.04535974973931178, 'mean_word_length': 5.149038461538462, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '417645', 'license': 'Apache-2.0', 'n_tokens_mistral': 1944, 'n_tokens_neox': 1981, 'n_words': 362, 'path': '_notebooks/2021-11-08-ENG-python-inflearn8.ipynb', 'repo_name': 'Jaysung00/jays_blog', 'size': '3838'}