[Python] 클로저

PurinYun·2023년 11월 10일
0

AIffel

목록 보기
10/75

변수의 범위

전역 변수: 전체에서 접근 가능한 변수
전역 범위: 그 변수에 접근가능한 범위
지역변수: 함수 내에서 만든 변수
지역범위: 그 변수에 접근가능한 범위

name = 'aiffel'  		# 전역 변수

def hi3():
    name = 'python'
    print(f'hi {name}!')   

hi3()
print(name)

hi python!
aiffel

global : 전역변수 불러오기

name = 'aiffel'  			# 전역 변수

def hi4():
    global name  			# 전역 변수 name을 가져오겠다!
    name = 'python'  		# 전역 변수 name 변경
    print(f'hi {name}!')   

hi4()
print(name)

hi python!
python

함수 안에서 전역 변수 만들기

def hey():
    global a  			# a를 전역 변수로 쓰겠다
    a = '푸린'  		   # 함수 안에 쓰인 변수
    print(f'hey {a}!')

hey()
print(a)

hey 푸린!
푸린

nonlocal :지역변수 불러오기

def hello():
    who = '푸린'  		# 지역 변수 생성
    def hello2():
        nonlocal who  	 # 지역 변수 who를 여기서도 쓰겠다.
        who = '아이펠'

    hello2()  			 # 안에 있던 hello2() 함수 실행
    print(f'hello {who}!')

hello()

hello 아이펠!

*nonlocal who 를 주석처리 하면
hello 푸린!
출력

클로저(closure)

: (어떤 함수의 내부함수가 외부함수의 변수(프리변수)를 참조할 때,
외부 함수가 종료된 후에도 내부 함수가 외부 함수의 변수를 참조할 수 있도록
어딘가에 저장하는 함수
:자신을 둘러싼 scope(name space)의 상태 값을 기억하는 함수

*프리변수(free variable)는 어떤 함수에서는 사용되지만 그 함수 내부에서는
선언되지 않은 변수를 의미

e.g. global, nonlocal, local 등..


def intro(home):
    introduction = 'My hometown is '+home+'.'

    def my():  						# 조건 1 충족
        print(introduction) 	 	# 조건 2 충족
    
    return my 						 # 조건 3 충족

함수명이 intro 이고, 매개변수로 home 을 받습니다.
함수 내부에서는 'My hometown is ' 와 home 을 결합한 문자열을
introduction 변수에 저장합니다.
그리고 my 라는 내부 함수를 선언하고,
이 함수는 introduction 변수를 출력합니다.
마지막으로, my 함수를 반환합니다.

클로저 함수의 조건

조건 1) 어떤 함수의 내부함수일 것
조건 2) 그 내부함수는 외부함수의 변수의 참조해야 함
조건 3) 외부함수가 내부함수를 리턴할 것

intro: 함수명
(home) : 매개변수
def my() : my라는 내부함수 선언
print() : ()안의 변수를 출력

def intro(home):
    introduction = 'My hometown is '+home+'.'

    def my():  
        print(introduction)  
    
    return my  

f = intro('Yeosu') 	    # 1
del intro  				# 2
f()  					# 3

My hometown is Yeosu.

(1)
intro 함수를 호출하여 my 함수를 반환받음.
home이라는 매개변수에는 'Yeosu'라는 값이 전달되어
'My hometown in Yeosu.' 라는 문자열이
introduction 이라는 변수에 저장됨.
그리고 my 함수가 f변수에 할당됨

intro('Yeosu')의 리턴값인 
my 함수 자체가 할당됩니다.

(2) 
전체 함수인 intro가 삭제되었습니다.
즉 메모리에서 함수가 삭제된 것입니다.
그렇다면 intro 안에 있던 변수 introduction도 함께 삭제됐을 것입니다.
하지만 intro함수가 삭제되더라도
이미 반환된 my함수는 이전에 할당받은 f변수에 저장되어 실행할 수 있다.

(3) 
F()라고 코드를 작성하면 f변수에 할당된 my함수가 호출됨.
my함수는 introduction 변수를 출력함.
(1)에서 언급했듯이 
f의 리턴값이 my이므로 
f()는 my()와 동일합니다.
그런데 # 2에서 my()를 감싼 외부 함수 intro를 삭제했기 때문에
당연히 내부 함수도 삭제됐을 것이라고 예상해서 오류가 나야하는데...?
오류 없이 값이 잘 출력된 것을 볼 수 있습니다.

클로저의 장점

1) 데이터 저장 가능 (삭제되어도^^)

2) 전역 변수 남용 방지

profile
Fantivation

0개의 댓글