파이썬 스코프 이해하기: 지역 변수와 전역 변수
지난 글에서는 함수가 계산한 값을 return으로 돌려주는 방법을 살펴봤어요. 그런데 함수 안에서 만든 변수는 함수 밖에서도 쓸 수 있을까요? 음... 직접 써 보면 의외로 헷갈리는 지점이 있습니다. 오늘은 변수가 어디에서 보이고 어디까지 살아 있는지, 스코프(scope)를 알아볼게요.
스코프는 변수의 활동 범위
스코프는 쉽게 말해 변수를 사용할 수 있는 범위예요. 파이썬은 변수를 만든 위치에 따라 그 변수를 찾을 수 있는 곳이 달라집니다.
함수 안에서 만든 변수는 보통 그 함수 안에서만 쓸 수 있어요. 이런 변수를 지역 변수라고 합니다. 함수 바깥에서 만든 변수는 전역 변수라고 부르고, 함수 안에서도 값을 읽을 수 있죠.
name = "민지" # 전역 변수
def say_hello():
message = "안녕, " + name # 지역 변수 message, 전역 변수 name 읽기
print(message)
say_hello()
print(name)
함수 안에서 name을 읽을 때는 함수 바깥에 있는 전역 변수를 찾습니다. 반면 message는 함수 안에서 만들었으니 함수 밖에서 바로 사용할 수 없어요. 변수마다 자기 구역이 있는 셈이죠.
지역 변수는 함수 안에서만
이 코드를 실행하면 어떻게 될까요?
def make_message():
message = "오늘도 한 줄씩!"
print(message)
make_message()
print(message) # 오류
print(message)가 함수 안에 있을 때는 잘 동작하지만, 마지막 줄에서는 message를 찾을 수 없어요. 함수가 실행될 때 만들어진 지역 변수는 그 함수 안에서 쓰기 위한 변수니까요.
처음엔 “분명 위에서 만들었는데 왜 못 찾아?” 싶을 수 있어요. 저도 예전에 함수 안에서 만든 임시 변수를 밖에서 꺼내 쓰려다 한참 헤맸습니다. 어? 변수가 증발한 것처럼 보였지만, 사실은 처음부터 바깥 구역에 놓인 적이 없었던 거예요.
함수 밖에서도 결과가 필요하다면 지난 글에서 본 return을 사용하면 됩니다.
def make_message():
message = "오늘도 한 줄씩!"
return message
result = make_message()
print(result)
지역 변수의 값을 반환받아 result에 담았어요. 함수가 내부에서 어떻게 계산했는지 감추고, 필요한 결과만 바깥에 전달하는 방식입니다.
전역 변수는 읽을 수 있지만 조심해서
전역 변수는 함수 바깥에서 만들고 여러 함수에서 읽을 수 있어요. 다만 함수 안에서 그 값을 바꾸려 할 때는 규칙이 하나 더 있습니다.
count = 0
def show_count():
print(count) # 전역 변수 읽기
show_count()
읽는 건 괜찮습니다. 그런데 함수 안에서 count = count + 1처럼 대입하면 파이썬은 함수 안의 count를 지역 변수로 판단해요. 아직 값이 정해지기 전에 읽으려는 상황이 되어 오류가 납니다.
count = 0
def add_one():
count = count + 1 # 오류: 지역 변수로 취급되지만 먼저 읽고 있음
전역 변수 자체를 바꾸려면 global을 선언할 수 있어요.
count = 0
def add_one():
global count
count += 1
add_one()
print(count) # 1
작동은 하지만, 함수가 바깥 상태를 직접 바꾸면 어느 곳에서 값이 변했는지 따라가기 어려워질 수 있어요. 여러 함수가 같은 전역 변수를 바꾸기 시작하면 “누가 숫자를 올렸지?” 하는 탐정 놀이가 열립니다. 솔직히 말하면, 디버깅할 때 그 탐정 모자는 별로 쓰고 싶지 않더라고요.
값은 인자로 받고 결과는 반환하기
전역 변수에 기대는 대신, 필요한 값은 함수의 매개변수로 전달하고 바뀐 결과는 반환하는 방법이 읽기 쉽습니다.
def add_one(count):
return count + 1
count = 0
count = add_one(count)
print(count) # 1
이제 함수만 봐도 어떤 값을 받아 어떤 결과를 만드는지 알 수 있죠. 함수 바깥의 상태를 몰래 바꾸지 않아서, 다른 곳에서 재사용하거나 고칠 때도 부담이 적습니다.
물론 전역 변수가 항상 나쁜 건 아니에요. 프로그램 전체에서 바뀌지 않는 설정값처럼 여러 곳에서 읽는 값에는 쓸 수 있습니다. 다만 자주 바뀌는 값이라면 인자와 반환값으로 흐름을 드러내는 편이 대체로 편해요.
변수 범위를 알면 함수가 선명해져요
오늘 내용은 이렇게 기억하면 됩니다.
- 함수 안에서 만든 변수는 지역 변수라서 보통 함수 안에서만 쓸 수 있어요.
- 함수 밖에서 만든 전역 변수는 함수 안에서 읽을 수 있지만, 수정하려면
global선언이 필요해요. - 함수 밖으로 값을 전달할 땐 전역 변수에 기대기보다
return으로 결과를 돌려주는 방법을 먼저 생각해 보세요.
앞에서 배운 매개변수와 반환값이 여기서도 꽤 든든하죠? 다음 글에서는 코드를 짧게 표현할 때 쓰는 람다 함수를 만나볼게요. 어디까지 짧게 줄여도 읽기 편할지, 같이 살펴봅시다.
(html comment removed: aistudio:footer )