본문 바로가기

진리는어디에/Python

[Python] 함수 #8 전역 변수와 지역 변수

이번 강좌에서는 파이썬의 전역 변수와 지역 변수에 대해 설명한다. 프로그래밍을 처음 접하는 분들에겐 접근 가능 범위와 생명 주기와 같은 용어가 생소하게 다가 올 수 있을 것이다. 생소한 용어라 당황스러울 수 있지만, 개념적으로 어렵거나 복잡한 내용은 아니므로 긴장하지 말고 가벼운 마음으로 따라오자.

프로그래밍에서는 변수의 선언 위치에 따라 변수의 유효 범위, 메모리 반환 시기, 초기화 여부가 달라진다. 크게는 전역 변수와 지역 변수로 나뉜다.

전역 변수는 프로그램이 시작하면서 종료 할 때까지 메모리에 상주하며, 프로그램 어디에서든 접근이 가능한 변수인 반면에 지역 변수는 함수와 같이 변수가 선언된 특정 코드 블록이 내에서만 접근이 가능하고 해당 블록이 종료 되면 변수 또한 메모리에서 해제된다. 또한 파이썬에서는 전역 변수와 지역 변수 외에 nonlocal이라는 특이한 형태의 변수도 존재한다. nonlocal 변수는 이 포스트의 마지막에 설명된다.

전역 변수

위에서 전역 변수란 프로그램이 시작 부터 종료 까지 유효한 변수라고 했다. 이는 프로그램이 살아 있는 동안 항상 메모리에 그 값을 유지하고 있다는 것을 의미한다. 또한 프로그램 어디에서든 접근이 가능하다고도 했다. 아래 예제를 통해 무슨 말인지 알아 보도록 하자.

전역 변수
프로그램 시작 부터 종료 까지 메모리에 상주하며 어디서든 접근이 가능한 변수
x = 0       # 전역 변수 x

def foo() :
    global x  # 함수 내에서 전역 변수에 접근하기 위해서는 global 키워드를 사용해야 한다
    x = 10
    print('x:', x)
    
print('x:', x)  # 0
foo()           # 10
print('x:', x)  # 10, foo함수 안에서 변경한 값이 그대로 유지 된다

프로그램의 시작 부분에 전역 변수 x를 선언하고 foo함수 안에서 값을 변경 했다(이것을 '접근' 했다고 표현 한다). 변경 된 값은 foo함수가 종료 된 뒤에도 여전히 그 값을 유지한다.

지역 변수

그럼 이번엔 지역 변수란 무엇인지 살펴보자. 지역 변수는 함수와 같은 특정 코드 블럭 내에서 선언 되어 그 내에서만 접근이 가능하고 해당 블록이 종료 되면 변수 또한 메모리에서 해제되는 특징을 가진다고 했다.

지역 변수
코드 블럭 내에서 선언 되어 그 안에서만 사용 가능한 변수
x = 0       # 전역 변수 x
y = 0       # 전역 변수 y

def foo() :
    global x  # 함수 내에서 전역 변수에 접근하기 위해서는 global 키워드를 사용해야 한다
    
    x = 10    # 전역 변수에 접근하여 10을 저장한다
    y = 20    # 여기서 선언된 y는 지역 변수다, 전역 변수 y와는 다른 변수다
    z = 30    # 지역 변수
    
    print(f'x:{x}, y:{y}, z:{z}')
    
print(f'x:{x}, y:{y}') # x:0, y:0
# print(f'x:{x}, y:{y}, z:{z}') 주석을 해제하면 선언되지 않은 변수라고 에러를 발생 한다.
foo()                  # x:10, y:20
print(f'x:{x}, y:{y}') # x:10, y:0
# print(f'x:{x}, y:{y}, z:{z}')

foo함수 블럭 안에서 선언된 y는 전역 변수 y와 이름은 같지만 global 키워드를 적용하지 않았기 때문에 블럭 내에서 새로 선언된 지역 변수로 취급된다. 결과를 보면 전역 변수 x는 foo 함수 내에서 변경 시킨 값을 함수 종료 이후에도 그대로 유지하지만, 전역 변수 y는 한번도 수정된적이 없기 때문에 여전히 0이다.

foo 함수 내에서 선언된 변수 y는 지역 변수로써 foo함수 내에서만 유지되고 종료와 함께 메모리에서 해제 된다.

위 예제에서 14라인의 주석을 해제하면 z라는 변수는 선언 된적이 없다고 에러를 발생 시킨다. 이는 foo 함수의 지역 변수인 z는 함수 외부에서는 존재하지 않기 때문이다.

nonlocal 변수

nonlocal 변수는 지역 변수와 전역 변수의 중간쯤 특성을 가진 변수다. nonlocal로 선언된 변수는 코드 블럭의 바깥 쪽, 즉, 바깥 함수에서 선언된 변수와 바인딩 된다.

x = 0       # 전역 변수 x

def foo() :
    x = 10
    def inner() :
        nonlocal  x              # foo함수에서 선언된 x와 바인딩
        x = 20
        print(f'x in inner:{x}') # x in inner:20
    
    inner()
    print(f'x in foo:{x}')       # x in foo:20, 처음엔 10이었지만 inner20으로 변경
    
foo()
print(f'x in global:{x}')        # x in global:0, 여전히 0이다.

inner 함수에서 nonlocal로 선언된 변수 x는 foo의 로컬 변수 x와 바인딩 된다. 그렇기 때문에 inner에서 수정한 변수 x의 값이 inner함수가 종료 되더라도 foo안에서는 계속 유지된다. 하지만 전역 변수 x에는 접근한적이 없기 때문에 전역 변수 x의 값은 여전이 0이다.

nonlocal 변수 사용시 주의 할 점이 한가지 있다. nonlocal 변수는 코드 블록 내에서만 사용 가능하며, 중첩 함수가 아닌 함수를 정의하고 전역 변수에 접근하는 것은 불가능 하다.

x = 0  # 전역 변수 x

def foo():
    nonlocal x
    x= 10
    
foo()  # SyntaxError: no binding for nonlocal 'x' found
print(x)

마치며

전역 변수와 지역 변수에서 어려울 것은 없다. 다만 파이썬에서는 전역 변수를 함수에서 접근하기 위해서는 global 키워드를 사용해야만 한다. 이 외에 파이썬에서 허용하는 전역 변수의 선언 순서라던지, 전역 변수지만 프로그램이 시작할 때 부터 생성되는 것이 아니라 필요 할 때 생성하는 것이라던지 파이썬에서 허용하는 부분들이 있는데, 당장 사용하기 편할지는 몰라도 코드의 유지보수를 어렵게 만드는 주범중의 하나기 때문에 굳이 소개하지는 않겠다.

다음 강의에서 부터는 파이썬의 핵심 기능 중의 하나인 데코레이터(Decorator)에 대해서 살펴 보도록 하겠다.

부록 1. 같이 보면 좋은 글

 

유익한 글이었다면 공감(❤) 버튼 꾹!! 추가 문의 사항은 댓글로!!