네임스페이스란 무엇인가?
파이썬에서 변수(variable)는 특정 객체에 매핑되는 이름, 즉 식별자입니다. 그리고 네임스페이스(namespace)는 이러한 변수 이름(키)과 그에 대응하는 객체(값)를 저장하는 일종의 사전(dictionary) 구조라고 할 수 있습니다.
쉽게 말해, 네임스페이스는 "어떤 이름이 어떤 객체를 가리키는가"를 관리하는 공간입니다. 파이썬은 이 네임스페이스를 통해 변수 이름과 실제 메모리상의 객체를 연결합니다.
지역 네임스페이스와 전역 네임스페이스
파이썬 코드는 지역(local) 네임스페이스와 전역(global) 네임스페이스에 있는 변수에 모두 접근할 수 있습니다.
만약 지역 변수와 전역 변수의 이름이 같다면 어떻게 될까요? 이 경우 지역 변수가 전역 변수를 가리게(shadowing) 됩니다. 즉, 함수 내부에서는 같은 이름의 전역 변수가 존재하더라도 지역 변수가 우선적으로 사용됩니다.
또한 각 함수는 자신만의 고유한 지역 네임스페이스를 가지며, 클래스의 메서드(method)도 일반 함수와 동일한 스코프(scope, 범위) 규칙을 따릅니다.
파이썬은 지역 변수와 전역 변수를 어떻게 판단할까?
흥미로운 점은, 파이썬이 변수의 범위를 명시적으로 선언하지 않아도 합리적인 추측을 통해 판단한다는 것입니다. 기본 규칙은 다음과 같습니다.
- 함수 안에서 값이 할당(대입)된 변수는 지역 변수로 간주됩니다.
- 함수 안에서 값을 읽기만 하는 변수는 전역 네임스페이스에서 찾습니다.
따라서 함수 내부에서 전역 변수의 값을 변경하고 싶다면, 반드시 먼저 global 문을 선언해야 합니다.
global 문의 역할
global VarName이라는 문장은 파이썬에게 "VarName은 전역 변수다"라고 알려주는 역할을 합니다. 이 선언이 있으면 파이썬은 더 이상 지역 네임스페이스에서 해당 변수를 찾지 않고, 전역 네임스페이스의 변수를 직접 참조하게 됩니다.
예제: UnboundLocalError 발생 원리
다음 예제를 살펴보겠습니다. 전역 네임스페이스에 Money라는 변수를 정의하고, 함수 AddMoney() 내부에서 Money에 값을 할당합니다.
#!/usr/bin/python3
Money = 2000
def AddMoney():
# 아래 줄의 주석을 해제하면 오류가 해결됩니다:
# global Money
Money = Money + 1
print(Money)
AddMoney()
print(Money)
함수 내부에서 Money = Money + 1처럼 값을 할당하고 있으므로, 파이썬은 Money를 지역 변수로 판단합니다. 그런데 문제는 할당이 이루어지기 이전에 지역 변수 Money의 값을 먼저 읽으려 한다는 점입니다. 아직 값이 설정되지 않은 지역 변수를 참조했기 때문에 다음과 같은 UnboundLocalError가 발생합니다.
UnboundLocalError: cannot access local variable 'Money' where it is not associated with a value
이 문제를 해결하려면 코드에서 보이듯이 # global Money 줄의 주석을 해제하면 됩니다. global 선언을 추가하면 함수 내부의 Money가 전역 변수를 가리키게 되어, 실행 결과는 다음과 같이 정상적으로 출력됩니다.
2001
2001
정리
- 변수는 객체에 매핑되는 이름이며, 네임스페이스는 이름과 객체의 매핑 정보를 담는 사전 구조입니다.
- 함수마다 독립적인 지역 네임스페이스가 존재하며, 이름이 겹치면 지역 변수가 전역 변수를 가립니다.
- 함수 내에서 값이 할당되면 파이썬은 자동으로 지역 변수로 간주합니다.
- 함수 안에서 전역 변수를 수정하려면 반드시
global키워드를 먼저 선언해야 합니다.