파이썬 초보에서 중수로 넘어가기 위한 관문인 변수와 스코프에 대해서 정리를 해보았다.
이걸 제대로 이해한다고 해도 아직 중수라고 하긴엔 무리가 있을 듯 싶지만..
변수와 스코프의 개념에 대한 자료를 볼 때 아래와 같은 코드를 보게된다.
# test.py
x = 1
def test():
x = 2
test()
print(x)
위의 코드를 실행해보면 x 는 당연히 2가 나와야 한다고 생각할 수 있지만, 결과는 1이다.
이유는 파이썬이 변수를 찾는 과정에 있고, 그 과정에서 namespace
라는 개념이 있기 때문이다.
x 가 1이 되는 이유를 말하자면,
test()
함수 내부에 있는x
는test()
라는 함수가 가지고 있는지역 네임스페이스(local namespace)
에 있기 때문에,전역 변수 x
에 접근하지 못하기 때문이다.
즉, 전역에 선언된 변수 x 는 test.py
라는 모듈에 속해있다.
test() 함수
안에 선언된 x
는 test() 함수
안에 속해있는 지역변수
이다.
아래 코드의 실행 결과를 보면 30, 20, 10
이다.
x = 10
def test():
x = 20
def test2():
x = 30
print(x)
test2()
print(x)
test()
print(x)
파이썬이 변수를 찾는 순서는 이렇게 지역 네임스페이스의 공간 > 전역 네임스페이스의 공간 > 빌트인 네임스페이스
가 된다.
빌트인 네임스페이스 (built-in namespace)
내장 변수 혹은 함수로 int, str 등이 있는데 일단 여기서는 건너 뛰기로 한다.
섀도우잉
이란 특정한 스코프 내에서 선언된 이름이 그 외부 스코프와 중첩되는 것 을 말한다. 네임 마스킹
이라고도 한다.
로컬 이름 공간이 우선적으로 참조되며 전역 변수는 엑세스되지 않는다.
간단하게 예를 들어보자.
x = 10
def test(x):
x = 20
def test2():
x = 30
print(x)
test2()
print(x)
test()
print(x)
위의 코드에서 전역 변수로 선언된 x 를 test() 함수의 파라미터로 넘겼을 때, 함수 내부에서 파라미터 x 가 사용되지 못한다. 특정한 스코프 test() 에서 사용하고 있는 x 라는 변수의 이름이 전역 변수의 이름과 중첩되기 때문이다.
전역 변수, 혹은 지역 변수를 특정한 스코프 내에서 사용해야 할 때가 있는데, 이 때 global
과 nonlocal
키워드를 사용한다.
# 테스트 1
x = 10
def test():
nonlocal x # 여기서 에러. x 는 글로벌 전역이기 때문에 nonlocal 과 맞지 않음.
x = 20
def test2():
nonlocal x
x = 30
print(x)
test2()
print(x)
test()
print(x)
x = 10
def test():
global x
x = 20
def test2():
nonlocal x
# 여기서 에러. x 를 nonlocal 로 선언해서 상위 스코프의 x 를 찾는데
# 찾고보니 x 가 global 변수임
x = 30
print(x)
test2()
print(x)
test()
print(x)
x = 10
def test():
global x
x = 20
def test2():
global x
x = 30
print(x)
test2()
print(x)
test()
print(x)
# 실행 결과
30
30
30
리턴
을 통해서 재할당 하는 식으로 한다.가급적이면 전역 변수를 내부에서 참조하지 않을 것을 권장한다. 전역 변수를 직접 읽기 보단 인자값으로 받아서 처리하게 되면 함수의 내부는 상위 스코프와 암시적인 영향을 주고 받지 않는 순수한 함수가 된다.
참조 링크