파이썬에서의 변수 선언은 다른 프로그래밍 언어와 조금 다르다. 선언자 없이 변수 = 값
형태로 선언하며 반드시 선언과 할당이 동시에 이루어져야 한다.
따라서 파이썬에서는 변수를 선언하고 값을 할당하는 것과 변수의 값을 변경하는 것이 아무런 차이가 없다. 항상 새로운 값을 할당한다고 생각하면 되겠다.
그래서 다른 프로그래밍 언어를 사용하다 파이썬으로 넘어오면 많이들 하는 실수가 있다. 예제로 알아보자.
a = 3
def func():
a = 4
func()
print(a)
# 결과: 3
위 코드는 전역변수 a
의 값을 4로 변경하라는 의도로 작성했다.
그러나 a
는 여전히 3이다. 왜 그럴까?
이것을 이해하려면 스코프를 알아야 한다. 스코프는 일단 변수가 선언된 공간으로 이해하자.
파이썬에서 스코프는 전역 그리고 지역 스코프가 존재한다. 스코프가 다르면 변수의 이름이 같아도 다른 변수로 취급된다.
위의 코드에서는 전역으로 a = 3
으로 선언이 되었고 함수 내의 지역 공간에 a = 4
라는 지역변수를 선언한 것이 된다.
a = 3
def func()
if a == 3:
print("a is 3")
func()
# 결과: a is 3
하지만 이렇게 참조를 하면 문제없이 a값을 사용할 수 있다.
안쪽 스코프에서 변수를 찾아보고 없으면 바깥으로 이동하면서 계속해서 찾기 때문이다.
리스트의 원소를 바꾸면 어떻게 될까?
a = [1, 2, 3]
def func():
a[0] = 4
func()
print(a)
# 결과: [4, 2, 3]
변수 자체에 할당하는 것이 아니라면 리스트, 딕셔너리 등 내부 원소를 변경하거나 할당하는 것은 새롭게 선언하는 것이 아니기 때문에 생각한대로 동작한다.
마지막으로 위의 내용을 인지하고도 많이 저지르는 실수가 있다.
a = 3
def func():
print(a, end=' ')
a = 5
print(a)
func()
# 결과: UnboundLocalError: local variable 'a' referenced before assignment
위 코드의 예상 결과는 3 5
가 출력되는 것이다.
왜 저런 오류가 발생했을까? 오류 메시지를 해석하자면 지역변수 'a'가 할당 전에 참조되었다.
라고 출력하고 있다.
이전에 스코프 내에 변수가 없으면 외부 스코프에서 찾는다고 하지 않았나? 라는 의문이 들 수 있다. 하지만 잘 보면 스코프 내에 a
라는 변수가 있다. 단지 print
문 뒤에 선언되었을 뿐이다.
이렇게 전역 변수를 사용할 것이라면 내부에서 값을 변경하려는 시도 자체를 하지 않는것이 좋다. 이렇게 명시적으로 발생하는 오류는 그나마 검출이 쉽지만 오류 없이 의도와 다르게 실행되기 시작하면 찾아내기 어렵다.