중첩 함수 내에서만 유효하다.
전역이 아닌 상위 스코프를 탐색한다.
실제 변수 바인딩: nonlocal로 선언된 변수를 수정하면 실제 상위 함수의 변수 값이 바뀐다.
사용하는 이유
1. 파이썬의 객체지향
def make_counter():
count = 0 # 상위 함수의 변수 (Enclosing variable)
def counter():
nonlocal count
count += 1 # count 값을 변경하기 위해 nonlocal 선언 필수
return count
return counter
my_counter = make_counter()
print(my_counter()) # 1
print(my_counter()) # 2
count 변수는 make_counter 호출이 끝난 뒤에도 메모리에 남아 my_counter를 호출할 때마다 값이 갱신된다.
2. 클로저(Closure) 구현
3. 캡슐화 (Encapsulation)
특정 함수에서만 접근 가능하도록 보호
FastAPI(Starlette) 내부의 nonlocal 활용 사례
주로 StreamingResponse(데이터를 끊어서 보낼 때)나 Timeout 처리 로직에서 '응답이 이미 시작되었는지' 혹은 '연결이 끊겼는지'를 체크하는 플래그(Flag)용으로 사용
async def some_asgi_app(scope, receive, send):
response_started = False # 응답 시작 여부를 기록하는 상태 변수
async def sender(message):
nonlocal response_started # 상위 함수의 변수를 수정하겠다고 선언
if message["type"] == "http.response.start":
response_started = True # 상태 업데이트
await send(message)
# 실제 비동기 로직 수행 중 sender 호출...
await sender({"type": "http.response.start", "status": 200})
if response_started:
# 응답이 이미 시작된 경우의 후속 처리
pass'스터디' 카테고리의 다른 글
| DJANGO 프로젝트의 Entry Point 및 내부 소스 분석 (0) | 2025.12.26 |
|---|