1.2전역 변수와 지역 변수
■ 전역 변수
전역 변수(global variable)는 전체 영역에서 접근할 수 있는 변수입니다. 따라서 함수 안에서도 접근할 수 있어야 합니다. 예제를 살펴보죠.
코드 5-1 function/global_1.py
g_var = 10 #1 def func(): print("g_var = {}".format(g_var)) if __name__ = = "__main__": func()
실행결과 g_var = 10
코드 5-1에서 g_var은 전역 변수입니다(#1). 함수 안에서 전역 변수에 접근했고, 실행 결과를 보면 접근이 가능하다는 것을 알 수 있습니다.
이번에는 함수 안에서 전역 변수의 변경을 시도해 보겠습니다.
코드 5-2 function/global_2.py
g_var = 10 #1 def func(): g_var = 20 #2 print("g_var = {} in function".format(g_var)) #3 if __name__ = = "__main__": func() print("g_var = {} in main".format(g_var)) #4
실행결과 g_var = 20 in function
g_var = 10 in main
전역 변수 g_var을 선언했고(#1) 함수 안에서 g_var 값의 변경을 시도합니다(#2). 전역 변수가 함수 안에서 변경되었는지 출력하여 확인해 봅니다(#3). 또한 함수 바깥 즉, 함수를 호출한 쪽에서 변경되었는지도 출력하여 확인해 봅니다(#4).
실행 결과를 보면 당혹스럽습니다. 분명 함수 안에서는 g_var 값이 20으로 변경되었는데 함수 바깥에서 확인해 보니 바뀌지 않았습니다. 왜 이런 결과가 나온 걸까요? 그 이유는 함수 안에서 전역 변수 g_var 값의 변경을 시도하기 위해 선언한 #2는 전역 변수를 변경하는 것이 아니라 함수 안에서 새로운 지역 변수 g_var을 생성한 것이기 때문입니다. 이 문장을 이해하려면 지역 변수의 개념을 알아야 합니다.
■ 지역 변수
지역 변수(local variable)는 전역 변수와 반대 개념입니다. 말 그대로 특정 지역에서만 접근할 수 있는 변수입니다. 특정 지역은 함수 내부를 의미합니다. 따라서 함수 안에서 선언한 변수가 지역 변수입니다. 지역 변수는 함수 바깥에서는 접근할 수 없고 함수가 호출될 때 생성되었다가 호출이 끝나면 사라집니다(이 말이 무슨 의미인지는 2절에서 알아봅니다).
코드 5-2에서 함수 안에서 변수를 선언하는 #2는 지역 변수를 생성하는 코드입니다. 그렇다면 함수 안에서는 전역 변수에 접근만 할 수 있고 변경은 할 수 없는 걸까요?
이 물음에 대한 대답은 ‘변경할 수 있다’입니다. 대신 함수 안에서 전역 변수를 변경하려면 특별한 문법이 필요합니다. 코드 5-2에서 실패한 전역 변수 변경을 이번에는 성공시켜 봅시다.
코드 5-3 function/global_3.py
g_var = 10 #1 def func(): global g_var #2 g_var = 20 #3 if _ _name__ = = "__main__": print("g_var : {} before".format(g_var)) func() print("g_var : {} after".format(g_var))
실행결과 g_var = 20 in function
g_var = 10 in main
코드 5-3을 보면 #1에서 선언한 전역 변수를 #3에서 변경하였습니다. 실행 결과를 보면 잘 변경된 것을 확인할 수 있는데 그 이유는 #2에서 global 키워드를 이용해 전역 변수 g_var을 함수 안에서 사용하겠다고 명시했기 때문입니다. 따라서 #3은 지역 변수를 따로 생성한 것이 아니라 전역 변수 g_var을 변경하는 것을 의미합니다.
전역 변수에 대한 접근과 변경에 대해 알아보았으니 지역 변수의 특징에 대해서도 알아보겠습니다.
■ nonlocal 키워드
함수 안에서 전역 변수를 변경할 수 있다는 것을 알았습니다. 이 개념을 조금 더 넓혀 볼까요?
함수를 정의할 때 함수 내부에서 다른 함수를 정의할 수 있습니다.
def outer():
a = 10 #1
def inner():
b = 20 #2
코드에서 outer() 함수에 지역 변수 a가 선언되었고(#1), 중첩된 함수 inner() 함수에 지역 변수 b가 선언되었습니다(#2). 한 가지 생각해 볼 문제는 inner() 함수에서 outer() 함수의 지역 변수인 a를 변경할 수 있는지입니다. 변수 a는 outer() 함수 입장에서는 지역 변수지만 inner() 함수 입장에서는 지역 변수가 아닙니다. inner() 함수의 지역 변수는 b입니다. 이번 절에서는 이 문제에 대해 고민해 봅시다.
코드 5-4 function/nonlocal_1.py
a = 1 def outer(): b = 2 c = 3 print(a, b, c) def inner(): d = 4 e = 5 print(a, b, c, d, e) #1 inner() if __name__ = = "__main__": outer()
실행결과 1 2 3
1 2 3 4 5
코드 5-4를 보면 outer() 함수의 공간에 b와 c가 있고 중첩된 inner() 함수의 공간에는 d와 e가 있습니다. inner() 함수에서는 전역 변수뿐만 아니라 outer() 함수의 공간에 있는 지역 변수에도 접근할 수 있습니다(#1). 하지만 전역 변수 예제에서 살펴본 것처럼 inner() 함수 안에서 b와 c를 바꾸려고 시도하면 outer() 함수 공간에 접근하는 것이 아니라 inner() 함수 공간 안에 b와 c라는 지역 변수를 생성합니다. b나 c는 전역 변수가 아니니 global 키워드를 사용할 수도 없습니다. inner() 함수 안에서 b와 c를 변경하려면 어떻게 해야 할까요?
nonlocal 키워드를 사용하면 됩니다. 키워드 nonlocal을 이용하는 예제를 만들어 봅시다.
코드 5-5 function/nonlocal_2.py
def outer(): a = 2 #1 b = 3 def inner(): nonlocal a #2 a = 100 #3 inner() print( "locals in outer : a = {}, b = {}".format(a, b)) if __name__ = = "__main__": outer()
실행결과 locals in outer : a = 100, b = 3
코드 5-5를 보면 #1에서 선언한 outer() 함수의 지역 변수 a를 #3에서 변경하였습니다. 실행 결과를 보면 잘 바뀌었습니다. #2에서 nonlocal 키워드로 inner() 함수 안에서 outer() 함수의 지역 변수 a를 사용할 것이라고 선언했기 때문입니다.