스코프와 네임스페이스
학습 목표
네임스페이스(Namespace)의 개념을 이해한다
LEGB 규칙에 따른 이름 해석 순서를 설명할 수 있다
global과 nonlocal 키워드의 용도를 이해한다
왜 중요한가
변수가 어디에서 접근 가능한지(스코프)를 이해하지 못하면, 의도치 않은 변수 충돌이나 데이터 변경이 발생합니다. 대규모 프로젝트에서 모듈 간 이름 충돌을 방지하고, 클로저와 데코레이터를 올바르게 사용하기 위해 스코프 이해가 필수적입니다.
네임스페이스
네임스페이스(Namespace)는 이름(변수명, 함수명 등)과 객체를 매핑하는 공간입니다.
# 서로 다른 네임스페이스에서 같은 이름 사용 가능
import math
def math_calc ():
pi = 3.14 # 지역 네임스페이스의 pi
return pi
print (math.pi) # math 모듈 네임스페이스의 pi: 3.14159...
print (math_calc()) # 지역 네임스페이스의 pi: 3.14
LEGB 규칙
Python은 변수를 찾을 때 LEGB 순서로 검색합니다.
스코프 범위 예시 L ocal현재 함수 내부 함수 내 변수 E nclosing외부 감싸는 함수 중첩 함수의 외부 함수 변수 G lobal모듈(파일) 수준 최상위 변수 B uilt-inPython 내장 print, len, range
x = "global" # Global
def outer ():
x = "enclosing" # Enclosing
def inner ():
x = "local" # Local
print (x) # "local" (L에서 찾음)
inner()
print (x) # "enclosing" (E에서 찾음)
outer()
print (x) # "global" (G에서 찾음)
print ( len ) # <built-in function len> (B에서 찾음)
global 키워드
함수 내에서 전역 변수를 수정할 때 사용합니다.
count = 0
def increment ():
global count # 전역 변수 count를 사용한다고 선언
count += 1
increment()
increment()
print (count) # 2
global은 가급적 사용을 피하세요. 전역 상태 변경은 코드를 예측하기 어렵게 만듭니다. 대신 매개변수와 반환값을 사용하세요.# 비추천 - global 사용
counter = 0
def increment ():
global counter
counter += 1
# 추천 - 매개변수/반환값 사용
def increment ( counter ):
return counter + 1
counter = 0
counter = increment(counter)
nonlocal 키워드
중첩 함수에서 외부 함수의 변수를 수정할 때 사용합니다.
def make_counter ():
count = 0
def increment ():
nonlocal count # 외부 함수의 count를 사용
count += 1
return count
return increment
counter = make_counter()
print (counter()) # 1
print (counter()) # 2
print (counter()) # 3
변수 수명주기
# 전역 변수: 프로그램 시작 ~ 종료
MAX_RETRY = 3
def process ():
# 지역 변수: 함수 호출 ~ 반환
result = []
for i in range ( 5 ):
# 루프 변수: Python에서는 루프 후에도 접근 가능!
temp = i * 2
result.append(temp)
print (i) # 4 (마지막 값 유지 - Python 특이사항)
print (temp) # 8 (루프 후에도 접근 가능)
return result
Python에서 for 루프의 변수는 루프 종료 후에도 접근 가능합니다. 이는 C/Java와 다른 Python의 특이한 점입니다.
AI/ML에서의 활용
# 클로저로 설정 기반 함수 생성
def make_preprocessor ( lowercase = True , max_length = 512 ):
"""설정에 따른 전처리 함수를 생성합니다."""
def preprocess ( text ):
# lowercase, max_length는 Enclosing 스코프에서 접근
if lowercase:
text = text.lower()
return text[:max_length]
return preprocess
preprocess_en = make_preprocessor( lowercase = True )
preprocess_ko = make_preprocessor( lowercase = False )
# 학습 상태 추적 (nonlocal 활용)
def make_trainer ():
best_loss = float ( "inf" )
epoch = 0
def train_step ( current_loss ):
nonlocal best_loss, epoch
epoch += 1
if current_loss < best_loss:
best_loss = current_loss
print ( f "Epoch { epoch } : 새로운 최고 기록! loss= { best_loss :.4f} " )
return best_loss
return train_step
내장 함수 이름을 변수로 사용하면 어떻게 되나요?
list = [1, 2, 3]처럼 내장 이름을 변수에 할당하면, Global 스코프에서 먼저 발견되어 내장 함수를 가리게 됩니다. list()를 호출하면 에러가 발생합니다. 내장 이름을 변수명으로 사용하지 마세요.
외부 함수의 변수를 기억하는 내부 함수입니다. 람다와 클로저 문서에서 자세히 다룹니다.
체크리스트
다음 문서